/*
 * Copyright (c) 2011-2014, fortiss GmbH.
 * Licensed under the Apache License, Version 2.0.
 *
 * Use, modification and distribution are subject to the terms specified
 * in the accompanying license file LICENSE.txt located at the root directory
 * of this software distribution. A copy is available at
 * http://chromosome.fortiss.org/.
 *
 * This file is part of CHROMOSOME.
 *
 * $Id$
 */

/**
 * \file
 *         Main file of node 'demonstrator'.
 *
 * \author
 *         This file has been generated by the CHROMOSOME Modeling Tool (XMT)
 *         (fortiss GmbH).
 */

/******************************************************************************/
/***   Includes                                                             ***/
/******************************************************************************/
#include "autoPnP/adv/exampleGUI/include/doSomethingFunction.h"
#include "autoPnP/adv/exampleGUI/include/doSomethingFunctionWrapper.h"
#include "autoPnP/adv/exampleGUI/include/exampleGUIComponent.h"
#include "autoPnP/adv/exampleGUI/include/exampleGUIComponentWrapper.h"
#include "autoPnP/adv/exampleGUI/include/exampleGUIManifest.h"
#include "autoPnP/topic/AutoPnPCommon.h"
#include "autoPnP/topic/AutoPnPCommonData.h"
#include "xme/core/broker/include/broker.h"
#include "xme/core/broker/include/brokerPnpManagerInterface.h"
#include "xme/core/dataHandler/include/dataHandlerConfigurator.h"
#include "xme/core/directory/include/nodeRegistryController.h"
#include "xme/core/directory/include/topicRegistry.h"
#include "xme/core/executionManager/include/executionManagerScheduleManagementInterface.h"
#include "xme/core/logUtils.h"
#include "xme/core/login/include-gen/loginClientComponent.h"
#include "xme/core/login/include-gen/loginClientComponentWrapper.h"
#include "xme/core/login/include-gen/loginClientManifest.h"
#include "xme/core/login/include-gen/loginClientProcessResponseFunction.h"
#include "xme/core/login/include-gen/loginClientProcessResponseFunctionWrapper.h"
#include "xme/core/login/include-gen/loginClientSendRequestFunction.h"
#include "xme/core/login/include-gen/loginClientSendRequestFunctionWrapper.h"
#include "xme/core/login/include/loginClient.h"
#include "xme/core/manifestRepository/include/manifestRepository.h"
#include "xme/core/node.h"
#include "xme/core/nodeManager/include/componentRepository.h"
#include "xme/core/nodeManager/include/componentRepositoryBuilder.h"
#include "xme/core/nodeManager/include/componentRepositoryPnpClientInterface.h"
#include "xme/core/plugAndPlay/include-gen/plugAndPlayClientComponent.h"
#include "xme/core/plugAndPlay/include-gen/plugAndPlayClientComponentWrapper.h"
#include "xme/core/plugAndPlay/include-gen/plugAndPlayClientProcessGraphFunction.h"
#include "xme/core/plugAndPlay/include-gen/plugAndPlayClientProcessGraphFunctionWrapper.h"
#include "xme/core/plugAndPlay/include-gen/plugAndPlayClientSendLogoutRequestFunction.h"
#include "xme/core/plugAndPlay/include-gen/plugAndPlayClientSendLogoutRequestFunctionWrapper.h"
#include "xme/core/plugAndPlay/include-gen/plugAndPlayClientSendManifestFunction.h"
#include "xme/core/plugAndPlay/include-gen/plugAndPlayClientSendManifestFunctionWrapper.h"
#include "xme/core/plugAndPlay/include-gen/plugAndPlayClientSendRemoveComponentRequestFunction.h"
#include "xme/core/plugAndPlay/include-gen/plugAndPlayClientSendRemoveComponentRequestFunctionWrapper.h"
#include "xme/core/plugAndPlay/include-gen/pnpClientManifest.h"
#include "xme/core/plugAndPlay/include/plugAndPlayClient.h"
#include "xme/core/topic.h"
#include "xme/core/topicData.h"
#include "xme/hal/include/cmdLine.h"
#include "xme/hal/include/context.h"
#include "xme/hal/include/env.h"
#include "xme/hal/include/mem.h"
#include "xme/hal/include/net.h"
#include "xme/hal/include/sched.h"
#include "xme/hal/include/sharedPtr.h"
#include "xme/hal/include/sync.h"
#include "xme/hal/include/time.h"
#include "xme/hal/include/tls.h"
#include "xme/wp/channel/include/channelInjector.h"
#include "xme/wp/channel/include/channelInjectorWayPointFunctionWrapper.h"
#include "xme/wp/channel/include/channelSelector.h"
#include "xme/wp/channel/include/channelSelectorWayPointFunctionWrapper.h"
#include "xme/wp/marshal/include-gen/demarshaler.h"
#include "xme/wp/marshal/include-gen/demarshalerFunctionWrapper.h"
#include "xme/wp/marshal/include-gen/marshaler.h"
#include "xme/wp/marshal/include-gen/marshalerFunctionWrapper.h"
#include "xme/wp/marshal/include/demarshaler.h"
#include "xme/wp/marshal/include/marshaler.h"
#include "xme/wp/udp/include/udpReceive.h"
#include "xme/wp/udp/include/udpReceiveWayPointFunctionWrapper.h"
#include "xme/wp/udp/include/udpSend.h"
#include "xme/wp/udp/include/udpSendWayPointFunctionWrapper.h"

#include <inttypes.h>

// PROTECTED REGION ID(DEMONSTRATOR_INCLUDES) ENABLED START
#include "xme/hal/include/qt.h"
// PROTECTED REGION END

/******************************************************************************/
/***   Variables                                                            ***/
/******************************************************************************/
/**
 * \brief Array of all ports on this node.
 *
 * \details Index | Port
 *              0 | exampleGUI.addComponent
 *              1 | loginClient.inResponse
 *              2 | loginClient.outRequest
 *              3 | loginClient.outLoginAcknowledgment
 *              4 | pnpClient.inLoginAcknowledgment
 *              5 | pnpClient.inGraph
 *              6 | pnpClient.outManifest
 *              7 | pnpClient.outLogoutAcknowledgment
 *              8 | pnpClient.outLogoutRequest
 *              9 | pnpClient.outRemoveComponentRequest
 *             10 | demarshaler.configuration[0].out (loginClient.inResponse)
 *             11 | demarshaler.configuration[1].out (pnpClient.inGraph)
 *             12 | demarshaler.configuration[0].in (loginClient.inResponse)
 *             13 | demarshaler.configuration[1].in (pnpClient.inGraph)
 *             14 | udpReceive.configuration[0].out (loginClient.inResponse)
 *             15 | udpReceive.configuration[1].out (pnpClient.inGraph)
 *             16 | marshaler.configuration[0].out (loginClient.outRequest)
 *             17 | marshaler.configuration[0].in (loginClient.outRequest)
 *             18 | udpSend.configuration[0].in (loginClient.outRequest)
 */
static xme_core_dataManager_dataPacketId_t ports[19];

/**
 * \brief Buffers required by UdpReceiveWaypoint.
 */
static void* udpReceiveBuffers[2];
/**
 * \brief Buffers required by UdpSendWaypoint.
 */
static void* udpSendBuffers[1];
static xme_core_exec_functionDescriptor_t* loginClientFuncDescs[2] = {NULL, NULL};
static xme_core_exec_functionDescriptor_t* pnpClientFuncDescs[4] = {NULL, NULL, NULL, NULL};
static xme_core_exec_functionDescriptor_t* exampleGUIFuncDescs[1] = {NULL};

static xme_core_exec_functionDescriptor_t* demarshalerWaypointDescriptor = NULL;
static xme_wp_waypoint_instanceId_t demarshalerWaypointInstanceIds[2] = { XME_WP_WAYPOINT_INSTANCEID_INVALID, XME_WP_WAYPOINT_INSTANCEID_INVALID };
static xme_core_exec_functionDescriptor_t* udpReceiveWaypointDescriptor = NULL;
static xme_wp_waypoint_instanceId_t udpReceiveWaypointInstanceIds[2] = { XME_WP_WAYPOINT_INSTANCEID_INVALID, XME_WP_WAYPOINT_INSTANCEID_INVALID };
static xme_core_exec_functionDescriptor_t* marshalerWaypointDescriptor = NULL;
static xme_wp_waypoint_instanceId_t marshalerWaypointInstanceIds[1] = { XME_WP_WAYPOINT_INSTANCEID_INVALID };
static xme_core_exec_functionDescriptor_t* udpSendWaypointDescriptor = NULL;
static xme_wp_waypoint_instanceId_t udpSendWaypointInstanceIds[1] = { XME_WP_WAYPOINT_INSTANCEID_INVALID };

/******************************************************************************/
/***   Prototypes                                                           ***/
/******************************************************************************/
XME_EXTERN_C_BEGIN

/**
 * \brief Initialize CHROMOSOME HAL and core components.
 *
 * \param[in] argc Number of command line arguments.
 * \param[in] argv Command line argument vector.
 *
 * \retval XME_STATUS_SUCCESS when initialization succeeded without problems.
 * \retval XME_STATUS_OUT_OF_RESOURCES when an error occured during initialization
 *         of one of the HAL or core components.
 */
xme_status_t
xmeInit
(
    int argc,
    char* argv[]
);

/**
 * \brief Finalize CHROMOSOME hal and core components.
 */
void
xmeFini(void);

/**
 * \brief Initialize data structures of pnp related components.
 *
 * \details Adds information about the initial components on this node to the
 *          logical route manager, plug and play manager and network
 *          communication manager.
 *
 * \retval XME_STATUS_SUCCESS when initialization succeeded without problems.
 * \retval XME_STATUS_OUT_OF_RESOURCES when an error occured during initialization.
 */
xme_status_t
pnpInit(void);

/**
 * \brief Announces all ports of the given component to the pnpClient.
 *        Components need to be created first, before calling this.
 *
 * \return XME_STATUS_SUCCESS if operation completed successfully.
 */
xme_status_t
announceComponentPortsToPnpClient
(
    xme_core_component_t componentID
);

/**
 * \brief Helper function for announceComponentPortsToPnpClient, which announces
 *        a single port.
 *
 * \param[in] componentHandle Handle of component to which the port belongs.
 * \param[in] componentID Component ID of component to which the port belongs.
 * \param[in] componentManifest Manifest of component to which the port belongs.
 * \param[in] initializationString Initialization string of component to which the port belongs.
 * \param[in] functionDescriptor Function descriptor of the function to which the port belongs.
 * \param[in] portIndex Index of the announced port in the component manifest.
 *
 * \return XME_STATUS_SUCCESS if operation completed successfully.
 */
xme_status_t
announceComponentPortToPnpClient
(
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle,
    xme_core_component_t componentID,
    const xme_core_componentManifest_t* const componentManifest,
    const char* const initializationString,
    const xme_core_exec_functionDescriptor_t* const functionDescriptor,
    uint16_t portIndex
);

/**
 * \brief Configures and activates the initial schedule for this node.
 */
void
configureSchedule(void);

/**
 * \brief Get the data packet ID of the given port. Can be used after createComponentInstances has been called.
 *
 * \param[in] componentID ID of the component to which the port belongs.
 * \param[in] portIndex Index of the port.
 *
 * \return The data packet ID of the port.
 */
xme_core_dataManager_dataPacketId_t
getDataPacketID
(
    xme_core_component_t componentID,
    uint16_t portIndex
);

/**
 * \brief Get a pointer to the function descriptor of the given function.
 *
 * \param[in] componentID ID of the component to which the function belongs.
 * \param[in] functionIndex Index of the function.
 *
 * \return The pointer to the function descriptor.
 */
xme_core_exec_functionDescriptor_t*
getFunctionDescriptor
(
    xme_core_component_t componentID,
    uint16_t functionIndex
);

/**
 * \brief Creates all component instances.
 *
 * \return XME_STATUS_SUCCESS if operation was successful.
 *         Ony any error we will shut down.
 */
xme_status_t
createComponentInstances(void);

/**
 * \brief Creates all waypoints and their configurations.
 */
void
createWaypoints(void);

/**
 * \brief Register attribute descriptor lists topic data sizes
 *        for each topic.
 *
 * \details This step is required before creating any ports that want to use
 *          attributes.
 *
 * \return XME_STATUS_SUCCESS if registration was successful, otherwise an
 *         error code.
 */
xme_status_t
registerTopicsAndAttributes(void);

/**
 * \brief Create and add manifests to manfiest repository for all known components types.
 */
void
createComponentTypeManifests(void);

/**
 * \brief Register all known components types in the logging system.
 */
void
registerComponentTypesInLoggingEngine(void);

/**
 * \brief Create demarshaler waypoint instance.
 *
 * \details Allocates and populates given function descriptor and calls init function of waypoint.
 *          All calls to this function after the first one will do nothing except for setting
 *          the descriptor to the previously allocated one.
 *
 * \param descriptor Will be set to a pointer to the allocation function descriptor.
 * \param componentId Component id that will be used in the function descriptor.
 *
 * \retval XME_STATUS_SUCCESS when initialization was succesful.
 * \retval XME_STATUS_OUT_OF_RESOURCES initialization failure due to insufficient resources.
 */
xme_status_t
createDemarshalerWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
);

/**
 * \brief Adds a configuration entry to the demarshaler waypoint.
 *
 * \details Creates and adds a configuration entry for the demarshaler waypoint.
 *          The required ports are also created.
 *
 * \param descriptor Function descriptor of this waypoint.
 * \param inputDataPort Pointer to port id that will be used for the created input port of the configuration.
 * \param inputPortQueueSize Queue size of the input port.
 * \param outputDataPort Pointer to port id that will be used for the created output port of the configuration.
 * \param instanceId Pointer where instanceId of created configuration will be written to.
 * \param topic Topic for this configuration.
 * \param sizeOfTopic Size of the topic data structure.
 * \param channelID Channel ID of the configuration.
 *
 * \retval XME_STATUS_SUCCESS when no errors occurred.
 * \retval XME_STATUS_INTERNAL_ERROR when an error occured.
 */
xme_status_t
demarshalerWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* inputDataPort,
    uint8_t inputPortQueueSize,
    xme_core_dataManager_dataPacketId_t* outputDataPort,
    xme_wp_waypoint_instanceId_t* instanceId,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_core_channelId_t channelID
);

/**
 * \brief Removes a configuration entry from the demarshaler waypoint.
 *
 * \param descriptor See parameter with the same name in demarshalerWaypointAddConfig.
 * \param inputDataPort See parameter with the same name in demarshalerWaypointAddConfig.
 * \param outputDataPort See parameter with the same name in demarshalerWaypointAddConfig.
 * \param instanceId See parameter with the same name in demarshalerWaypointAddConfig.
 *
 * \retval XME_STATUS_SUCCESS always.
 */
xme_status_t
demarshalerWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* inputDataPort,
    xme_core_dataManager_dataPacketId_t* outputDataPort,
    xme_wp_waypoint_instanceId_t instanceId
);

/**
 * \brief Free resources allocated by this waypoint.
 */
void
destroyDemarshalerWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
);
/**
 * \brief Create udp receive waypoint instance.
 *
 * \details Allocates and populates given function descriptor and calls init function of waypoint.
 *          All calls to this function after the first one will do nothing except for setting
 *          the descriptor to the previously allocated one.
 *
 * \param descriptor Will be set to a pointer to the allocation function descriptor.
 * \param componentId Component id that will be used in the function descriptor.
 *
 * \retval XME_STATUS_SUCCESS when initialization was succesful.
 * \retval XME_STATUS_OUT_OF_RESOURCES initialization failure due to insufficient resources.
 */
xme_status_t
createUdpReceiveWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
);

/**
 * \brief Adds a configuration entry to the udp receive waypoint.
 *
 * \details Creates and adds configuration structure for udp receive waypoint.
 *          The required port and buffer are also created.
 *
 * \param descriptor Function descriptor of this waypoint.
 * \param dataPort Pointer to port id that will be used for the created port of the configuration.
 * \param key See key parameter of xme_wp_udp_udpReceive_addConfig.
 * \param ipPort See port parameter of xme_wp_udp_udpReceive_addConfig.
 * \param topic Topic for this configuration.
 * \param sizeOfTopic Size of the topic data structure.
 * \param instanceId See instanceId parameter of xme_wp_udp_udpReceive_addConfig.
 * \param recvBuffer See buffer parameter of xme_wp_udp_udpReceive_addConfig.
 *
 * \retval XME_STATUS_SUCCESS when no errors occurred.
 * \retval XME_STATUS_INTERNAL_ERROR when an error occured.
 */
xme_status_t
udpReceiveWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* dataPort,
    uint8_t* key,
    uint32_t ipPort,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_wp_waypoint_instanceId_t* instanceId,
    void** recvBuffer
);

/**
 * \brief Removes a configuration entry from the udp receive waypoint.
 *
 * \param descriptor See parameter with the same name in udpReceiveWaypointAddConfig.
 * \param dataPort See parameter with the same name in udpReceiveWaypointAddConfig.
 * \param instanceId See parameter with the same name in udpReceiveWaypointAddConfig.
 * \param recvBuffer See parameter with the same name in udpReceiveWaypointAddConfig.
 *
 * \retval XME_STATUS_SUCCESS always.
 */
xme_status_t
udpReceiveWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* dataPort,
    xme_wp_waypoint_instanceId_t instanceId,
    void* recvBuffer
);

/**
 * \brief  Free resources allocated by this waypoint.
 */
void
destroyUdpReceiveWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
);
/**
 * \brief Create marshaler waypoint instance.
 *
 * \details Allocates and populates given function descriptor and calls init function of waypoint.
 *          All calls to this function after the first one will do nothing except for setting
 *          the descriptor to the previously allocated one.
 *
 * \param descriptor Will be set to a pointer to the allocation function descriptor.
 * \param componentId Component id that will be used in the function descriptor.
 *
 * \retval XME_STATUS_SUCCESS when initialization was succesful.
 * \retval XME_STATUS_OUT_OF_RESOURCES initialization failure due to insufficient resources.
 */
xme_status_t
createMarshalerWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
);

/**
 * \brief Adds a configuration entry to the marshaler waypoint.
 *
 * \details Creates and adds a configuration entry for the marshaler waypoint.
 *          The required ports are also created.
 *
 * \param descriptor Function descriptor of this waypoint.
 * \param inputDataPort Pointer to port id that will be used for the created input port of the configuration.
 * \param inputPortQueueSize Queue size of the input port.
 * \param outputDataPort Pointer to port id that will be used for the created output port of the configuration.
 * \param instanceId Pointer where instanceId of created configuration will be written to.
 * \param topic Topic for this configuration.
 * \param sizeOfTopic Size of the topic data structure.
 * \param channelID Channel ID of the configuration.
 *
 * \retval XME_STATUS_SUCCESS when no errors occurred.
 * \retval XME_STATUS_INTERNAL_ERROR when an error occured.
 */
xme_status_t
marshalerWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* inputDataPort,
    uint8_t inputPortQueueSize,
    xme_core_dataManager_dataPacketId_t* outputDataPort,
    xme_wp_waypoint_instanceId_t* instanceId,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_core_channelId_t channelID
);

/**
 * \brief Removes a configuration entry from the marshaler waypoint.
 *
 * \param descriptor See parameter with the same name in marshalerWaypointAddConfig.
 * \param inputDataPort See parameter with the same name in marshalerWaypointAddConfig.
 * \param outputDataPort See parameter with the same name in marshalerWaypointAddConfig.
 * \param instanceId See parameter with the same name in marshalerWaypointAddConfig.
 *
 * \retval XME_STATUS_SUCCESS always.
 */
xme_status_t
marshalerWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* inputDataPort,
    xme_core_dataManager_dataPacketId_t* outputDataPort,
    xme_wp_waypoint_instanceId_t instanceId
);

/**
 * \brief  Free resources allocated by this waypoint.
 */
void
destroyMarshalerWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
);
/**
 * \brief  Create udp send waypoint instance.
 *
 * \details Allocates and populates given function descriptor and calls init function of waypoint.
 *          All calls to this function after the first one will do nothing except for setting
 *          the descriptor to the previously allocated one.
 *
 * \param descriptor Will be set to a pointer to the allocation function descriptor.
 * \param componentId Component id that will be used in the function descriptor.
 *
 * \retval XME_STATUS_SUCCESS when initialization was succesful.
 * \retval XME_STATUS_OUT_OF_RESOURCES initialization failure due to insufficient resources.
 */
xme_status_t
createUdpSendWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
);

/**
 * \brief Adds a configuration entry to the udp send waypoint.
 *
 * \details Creates and adds configuration structure for udp send waypoint.
 *          The required port and buffer are also created.
 *
 * \param descriptor Function descriptor of this waypoint.
 * \param dataPort Pointer to port id that will be used for the created port of the configuration.
 * \param key See key parameter of xme_wp_udp_udpSend_addConfig.
 * \param destIP See hostname parameter of xme_wp_udp_udpSend_addConfig.
 * \param ipPort See port parameter of xme_wp_udp_udpSend_addConfig.
 * \param topic Topic for this configuration.
 * \param sizeOfTopic Size of the topic data structure.
 * \param instanceId See instanceId parameter of xme_wp_udp_udpSend_addConfig.
 * \param sendBuffer See buffer parameter of xme_wp_udp_udpSend_addConfig.
 *
 * \retval XME_STATUS_SUCCESS when no errors occurred.
 * \retval XME_STATUS_INTERNAL_ERROR when an error occured.
 */
xme_status_t
udpSendWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* dataPort,
    uint8_t* key,
    const char* destIP,
    uint32_t ipPort,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_wp_waypoint_instanceId_t* instanceId,
    void** sendBuffer,
    bool isBroadcast
);

/**
 * \brief Removes a configuration entry from the udp send waypoint.
 *
 * \param descriptor See parameter with the same name in udpSendWaypointAddConfig.
 * \param dataPort See parameter with the same name in udpSendWaypointAddConfig.
 * \param instanceId See parameter with the same name in udpSendWaypointAddConfig.
 * \param sendBuffer See parameter with the same name in udpSendWaypointAddConfig.
 *
 * \retval XME_STATUS_SUCCESS always.
 */
xme_status_t
udpSendWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* dataPort,
    xme_wp_waypoint_instanceId_t instanceId,
    void* sendBuffer
);

/**
 * \brief Free resources allocated by this waypoint.
 */
void
destroyUdpSendWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
);
/**
 * \brief Create channel injector waypoint instance.
 *
 * \details Allocates and populates given function descriptor and calls init function of waypoint.
 *          All calls to this function after the first one will do nothing except for setting
 *          the descriptor to the previously allocated one.
 *
 * \param descriptor Will be set to a pointer to the allocation function descriptor.
 * \param componentId Component id that will be used in the function descriptor.
 *
 * \retval XME_STATUS_SUCCESS when initialization was succesful.
 * \retval XME_STATUS_OUT_OF_RESOURCES initialization failure due to insufficient resources.
 */
xme_status_t
createChannelInjectorWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
);

/**
 * \brief Adds a configuration entry to the channel injector waypoint.
 *
 * \details Creates and adds configuration structure for channel injector waypoint.
 *          The required port and buffer are also created.
 *
 * \param descriptor Function descriptor of this waypoint configuration.
 * \param inputPort Pointer to port id that will be used for the input of the configuration.
 * \param inputPortQueueSize Queue size of the input port.
 * \param outputPort Pointer to port id that will be used for the output port of the configuration.
 * \param injectedChannelID the channel identificator.
 * \param topic Topic for this configuration.
 * \param sizeOfTopic Size of the topic data structure.
 * \param instanceId See instanceId parameter of xme_wp_channel_channelInjector_addConfig.
 * \param recvBuffer See buffer parameter of xme_wp_channel_channelInjector_addConfig.
 *
 * \retval XME_STATUS_SUCCESS when no errors occurred.
 * \retval XME_STATUS_INTERNAL_ERROR when an error occured.
 */
xme_status_t
channelInjectorWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* inputPort,
    uint8_t inputPortQueueSize,
    xme_core_dataManager_dataPacketId_t* outputPort,
    xme_core_channelId_t injectedChannelID,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_wp_waypoint_instanceId_t* instanceId,
    void** recvBuffer
);

/**
 * \brief Removes a configuration entry from the channel injector waypoint.
 *
 * \param descriptor See parameter with the same name in channelInjectorWaypointAddConfig.
 * \param instanceId See parameter with the same name in channelInjectorWaypointAddConfig.
 * \param inputPort See parameter with the same name in channelInjectorWaypointAddConfig.
 * \param outputPort See parameter with the same name in channelInjectorWaypointAddConfig.
 * \param recvBuffer See parameter with the same name in channelInjectorWaypointAddConfig.
 *
 * \retval XME_STATUS_SUCCESS always.
 */
xme_status_t
channelInjectorWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_wp_waypoint_instanceId_t instanceId,
    xme_core_dataManager_dataPacketId_t* inputPort,
    xme_core_dataManager_dataPacketId_t* outputPort,
    void* recvBuffer
);

/**
 * \brief  Free resources allocated by this waypoint.
 */
void
destroyChannelInjectorWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
);
/**
 * \brief Create channel selector waypoint instance.
 *
 * \details Allocates and populates given function descriptor and calls init function of waypoint.
 *          All calls to this function after the first one will do nothing except for setting
 *          the descriptor to the previously allocated one.
 *
 * \param descriptor Will be set to a pointer to the allocation function descriptor.
 * \param componentId Component id that will be used in the function descriptor.
 *
 * \retval XME_STATUS_SUCCESS when initialization was succesful.
 * \retval XME_STATUS_OUT_OF_RESOURCES initialization failure due to insufficient resources.
 */
xme_status_t
createChannelSelectorWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
);

/**
 * \brief Adds a configuration entry to the channel selector waypoint.
 *
 * \details Creates and adds configuration structure for channel selector waypoint.
 *          The required port and buffer are also created.
 *
 * \param descriptor Function descriptor of this waypoint.
 * \param instanceId See instanceId parameter of xme_wp_channel_channelSelector_addConfig.
 * \param topic Topic for this configuration.
 * \param sizeOfTopic Size of the topic data structure.
 * \param inputPort Pointer to port id that will be used for the created input port of the configuration.
 * \param inputPortQueueSize Queue size of the input port.
 * \param outputPort Pointer to port id that will be used for the created output port of the configuration.
 * \param sourceChannelID the source channel identificator.
 * \param destinationChannelID the destination channel identificator.
 * \param recvBuffer See buffer parameter of xme_wp_channel_channelSelector_addConfig.
 *
 * \retval XME_STATUS_SUCCESS when no errors occurred.
 * \retval XME_STATUS_INTERNAL_ERROR when an error occured.
 */
xme_status_t
channelSelectorWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_wp_waypoint_instanceId_t* instanceId,
    xme_core_dataManager_dataPacketId_t* inputPort,
    uint8_t inputPortQueueSize,
    xme_core_dataManager_dataPacketId_t* outputPort,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_core_channelId_t sourceChannelID,
    xme_core_channelId_t destinationChannelID,
    void** recvBuffer
);

/**
 * \brief Removes a configuration entry from the channel selector waypoint.
 *
 * \param descriptor See parameter with the same name in channelSelectorWaypointAddConfig.
 * \param instanceId See parameter with the same name in channelSelectorWaypointAddConfig.
 * \param inputPort See parameter with the same name in channelSelectorWaypointAddConfig.
 * \param outputPort See parameter with the same name in channelSelectorWaypointAddConfig.
 * \param topic See parameter with the same name in channelSelectorWaypointAddConfig.
 * \param sourceChannelID See parameter with the same name in channelSelectorWaypointAddConfig.
 * \param destinationChannelID See parameter with the same name in channelSelectorWaypointAddConfig.
 * \param recvBuffer See parameter with the same name in channelSelectorWaypointAddConfig.
 *
 * \retval XME_STATUS_SUCCESS always.
 */
xme_status_t
channelSelectorWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_wp_waypoint_instanceId_t instanceId,
    xme_core_dataManager_dataPacketId_t* inputPort,
    xme_core_dataManager_dataPacketId_t* outputPort,
    xme_core_topic_t topic,
    xme_core_channelId_t sourceChannelID,
    xme_core_channelId_t destinationChannelID,
    void* recvBuffer
);

/**
 * \brief  Free resources allocated by this waypoint.
 */
void
destroyChannelSelectorWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
);
/**
 * \brief Add packet transfer entries for all ports to the broker.
 *
 * \retval XME_STATUS_SUCCESS if operation is scuccessful.
 * \retval XME_STATUS_INTERNAL_ERROR if an error occurred.
 */
xme_status_t
addDataPacketTransferEntries(void);

static char g_addressBuffer[128] = "127.0.0.1:65100";
static char g_addressBufferMulti[128] = "255.255.255.255";

XME_EXTERN_C_END

/******************************************************************************/
/***   Implementation                                                       ***/
/******************************************************************************/
xme_status_t
xmeInit
(
    int argc,
    char* argv[]
)
{
    XME_CHECK(XME_STATUS_SUCCESS == xme_core_log_logUtils_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_hal_cmdLine_init(argc, argv, "v::", 1), XME_STATUS_OUT_OF_RESOURCES);

    // Parse command line options. Do this right here to ensure that
    // the settings are applied before further processing is started.
    {
        int c;
        while (-1 != (c = xme_hal_cmdLine_getNextOption()))
        {
            switch (c)
            {
                case 'v':
                {
                    int logLevel = xme_hal_cmdLine_getIntegerOptionArgument(-3, 2, 1);
                    xme_log_severity_t severity;
                    switch (logLevel)
                    {
                        case -3:
                            severity = XME_LOG_FATAL;
                            break;
                        case -2:
                            severity = XME_LOG_ERROR;
                            break;
                        case -1:
                            severity = XME_LOG_WARNING;
                            break;
                        case 0:
                            severity = XME_LOG_NOTE;
                            break;
                        case 1:
                            severity = XME_LOG_VERBOSE;
                            break;
                        case 2:
                            severity = XME_LOG_DEBUG;
                            break;
                        default:
                            severity = XME_LOG_NOTE;
                    }
                    xme_core_log_setMinimumLogSeverityLevel(severity);
                    break;
                }

                default:
                    XME_LOG(XME_LOG_ERROR, "Unknown option '%c'!\n", c);
            }
        }
    }

	for(int i=0; i<argc-1; i++) {
		if(strcmp(argv[i], "master")==0)
			strcpy(g_addressBuffer, argv[i+1]);
		if(strcmp(argv[i], "multi")==0)
			strcpy(g_addressBufferMulti, argv[i+1]);
	}

    XME_CHECK(XME_STATUS_SUCCESS == xme_hal_env_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_hal_sync_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_hal_sched_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_core_directory_attribute_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_core_directory_nodeRegistryController_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_core_manifestRepository_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_core_dataHandler_init(), XME_STATUS_OUT_OF_RESOURCES);
    {
        xme_core_exec_configStruct_t configStruct = { NULL };
        XME_CHECK(XME_STATUS_SUCCESS == xme_core_exec_init(&configStruct), XME_STATUS_OUT_OF_RESOURCES);
    }
    XME_CHECK(XME_STATUS_SUCCESS == xme_hal_sharedPtr_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_hal_tls_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_hal_context_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_hal_net_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_core_nodeMgr_compRep_init(), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_core_broker_init(NULL), XME_STATUS_OUT_OF_RESOURCES);
    XME_CHECK(XME_STATUS_SUCCESS == xme_core_node_init(), XME_STATUS_OUT_OF_RESOURCES);

    registerComponentTypesInLoggingEngine();

    XME_CHECK(XME_STATUS_SUCCESS == xme_core_pnp_pnpClient_init(), XME_STATUS_OUT_OF_RESOURCES);

    //TODO: Remove protected region when issue #3982 has been resolved!
    // PROTECTED REGION ID(DEMONSTRATOR_XME_INIT) ENABLED START
	XME_CHECK(XME_STATUS_SUCCESS == xme_hal_qt_init(), XME_STATUS_OUT_OF_RESOURCES);
    // PROTECTED REGION END

    // Add interface to node registry
    {
        xme_com_interface_address_t interfaceAddress;
        /*char addressBuffer[22];

        XME_CHECK_MSG
        (
            XME_STATUS_SUCCESS == xme_hal_net_getInterfaceAddr(NULL, XME_COM_INTERFACE_ADDRESS_TYPE_IPV4, addressBuffer),
            XME_STATUS_INTERNAL_ERROR,
            XME_LOG_FATAL,
            "Unable to get the interface address of the local node.\n"
        );

        (void)xme_hal_safeString_strncat(addressBuffer, ":65100", sizeof(addressBuffer));*/

        XME_LOG
        (
            XME_LOG_NOTE,
            "Node operates on network interface address: %s\n",
            g_addressBuffer
        );

        xme_com_interface_ipv4StringToGenericAddress(g_addressBuffer, &interfaceAddress);
        xme_core_node_addInterface(interfaceAddress);
    }

    xme_core_node_setNodeName("demonstrator");

    return XME_STATUS_SUCCESS;
}

void
xmeFini(void)
{
	//TODO: Remove protected region when issue #3982 has been resolved!
    // PROTECTED REGION ID(DEMONSTRATOR_XME_FINI) ENABLED START
	xme_hal_qt_fini();
    // PROTECTED REGION END

    xme_core_node_fini();
    xme_core_broker_fini();
    xme_core_nodeMgr_compRep_fini();
    xme_hal_net_fini();
    xme_hal_context_fini();
    xme_hal_tls_fini();
    xme_hal_sharedPtr_fini();
    xme_core_dataHandler_fini();
    xme_core_manifestRepository_fini();
    xme_core_directory_nodeRegistryController_fini();
    xme_core_directory_attribute_fini();
    xme_hal_sched_fini();
    xme_hal_sync_fini();
    xme_hal_env_fini();
    xme_hal_cmdLine_fini();
    xme_core_log_logUtils_fini();
}

xme_status_t
pnpInit(void)
{
    announceComponentPortsToPnpClient((xme_core_component_t)2); // Component 'loginClient' of type 'loginClient'
    announceComponentPortsToPnpClient((xme_core_component_t)4); // Component 'pnpClient' of type 'pnpClient'
    announceComponentPortsToPnpClient((xme_core_component_t)130); // Component 'exampleGUI' of type 'exampleGUI'

    return XME_STATUS_SUCCESS;
}

xme_status_t
announceComponentPortToPnpClient
(
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle,
    xme_core_component_t componentID,
    const xme_core_componentManifest_t* const componentManifest,
    const char* const initializationString,
    const xme_core_exec_functionDescriptor_t* const functionDescriptor,
    uint16_t portIndex
)
{
    xme_status_t status = XME_STATUS_INTERNAL_ERROR;
    xme_core_nodeMgr_compRep_portHandle_t portHandle;
    const xme_core_componentPortManifest_t* portManifest = NULL;
    uint16_t topicSize = 0u;
    xme_core_dataManager_dataPacketId_t dataPacketID = XME_CORE_DATAMANAGER_DATAPACKETID_INVALID;

    portManifest = &(componentManifest->portManifests[portIndex]);

    status = xme_core_directory_topicRegistry_getTopicSize(portManifest->topic, &topicSize);
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d\n", __FILE__, __LINE__);

    portHandle = xme_core_nodeMgr_compRep_getPort(componentHandle, portIndex);

    dataPacketID = xme_core_nodeMgr_compRep_getDataPacketID(portHandle);

    status = xme_core_pnp_pnpClient_announceStaticComponentPort
    (
        portManifest->portType,
        portManifest->topic,
        topicSize,
        dataPacketID,
        componentManifest->componentType,
        initializationString,
        componentID,
        (xme_core_exec_functionDescriptor_t*)functionDescriptor // TODO: Const specifier ignored (issue #3999)
    );
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d\n", __FILE__, __LINE__);

    return XME_STATUS_SUCCESS;
}

xme_status_t
announceComponentPortsToPnpClient
(
    xme_core_component_t componentID
)
{
    xme_status_t status = XME_STATUS_INTERNAL_ERROR;
    xme_core_componentManifest_t componentManifest;
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle;
    xme_core_componentType_t componentType;
    const char* initializationString = NULL;
    uint16_t portCount = 0u;
    uint16_t portIndex = 0u;
    uint16_t funcCount = 0u;
    uint16_t funcIndex = 0u;

    status = xme_core_nodeMgr_compRep_getComponentInstance(XME_CORE_NODE_LOCAL_NODE_ID, componentID, &componentHandle);
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d\n", __FILE__, __LINE__);

    componentType = xme_core_nodeMgr_compRep_getComponentType(componentHandle);

    status = xme_core_manifestRepository_findComponentManifest
    (
        componentType,
        &componentManifest
    );
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d\n", __FILE__, __LINE__);

    initializationString = xme_core_nodeMgr_compRep_getInitializationString(componentHandle);

    portCount = xme_core_manifestRepository_getPortCount(&componentManifest);

    for (portIndex = 0u; portIndex < portCount; portIndex++)
    {
        announceComponentPortToPnpClient(componentHandle, componentID, &componentManifest,
                initializationString, NULL, portIndex);
    }

    funcCount = xme_core_manifestRepository_getFunctionCount(&componentManifest);

    for (funcIndex = 0u; funcIndex < funcCount; funcIndex++)
    {
        xme_core_nodeMgr_compRep_functionHandle_t functionHandle;
        const xme_core_exec_functionDescriptor_t* functionDescriptor;
        xme_core_functionManifest_t* functionManifest = &(componentManifest.functionManifests[funcIndex]);

        functionHandle = xme_core_nodeMgr_compRep_getFunction(componentHandle, funcIndex);

        functionDescriptor = xme_core_nodeMgr_compRep_getFunctionDescriptor(functionHandle);

        for (portIndex = 0u; portIndex < functionManifest->requiredPortIndicesLength; portIndex++)
        {
            announceComponentPortToPnpClient(componentHandle, componentID, &componentManifest,
                initializationString, functionDescriptor, functionManifest->requiredPortIndices[portIndex]);
        }
        for (portIndex = 0u; portIndex < functionManifest->optionalPortIndicesLength; portIndex++)
        {
            announceComponentPortToPnpClient(componentHandle, componentID, &componentManifest,
                initializationString, functionDescriptor, functionManifest->optionalPortIndices[portIndex]);
        }
    }

    return XME_STATUS_SUCCESS;
}

// Disable warning about unexpected exceptions. See issue #3848.
#if _MSC_VER && defined(__cplusplus)
    #pragma warning( push )
    #pragma warning( disable : 4297 )
#endif

void
configureSchedule(void)
{
    xme_status_t status;
    xme_core_exec_schedule_handle_t scheduleId;
    xme_core_exec_schedule_table_t* nodeSchedules[1];

    // Execution Manager and Scheduler

    // Configure dispatcher
    // Component 'loginClient' function 'loginClientSendRequest'
    if (NULL != loginClientFuncDescs[0])
    {
        status = xme_core_exec_dispatcher_createFunctionExecutionUnit(loginClientFuncDescs[0], true);
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    // Component 'loginClient' function 'loginClientProcessResponse'
    if (NULL != loginClientFuncDescs[1])
    {
        status = xme_core_exec_dispatcher_createFunctionExecutionUnit(loginClientFuncDescs[1], true);
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    // Component 'pnpClient' function 'pnpClientSendManifest'
    if (NULL != pnpClientFuncDescs[0])
    {
        status = xme_core_exec_dispatcher_createFunctionExecutionUnit(pnpClientFuncDescs[0], true);
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    // Component 'pnpClient' function 'pnpClientProcessGraph'
    if (NULL != pnpClientFuncDescs[1])
    {
        status = xme_core_exec_dispatcher_createFunctionExecutionUnit(pnpClientFuncDescs[1], true);
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    // Component 'pnpClient' function 'pnpClientSendLogoutRequest'
    if (NULL != pnpClientFuncDescs[2])
    {
        status = xme_core_exec_dispatcher_createFunctionExecutionUnit(pnpClientFuncDescs[2], true);
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    // Component 'pnpClient' function 'pnpClientSendRemoveComponentRequest'
    if (NULL != pnpClientFuncDescs[3])
    {
        status = xme_core_exec_dispatcher_createFunctionExecutionUnit(pnpClientFuncDescs[3], true);
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    // Component 'exampleGUI' function 'doSomething'
    if (NULL != exampleGUIFuncDescs[0])
    {
        status = xme_core_exec_dispatcher_createFunctionExecutionUnit(exampleGUIFuncDescs[0], true);
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }

    // Configure schedule
    xme_core_exec_scheduler_createScheduleTable
    (
        &(nodeSchedules[0]),
        xme_hal_time_timeIntervalFromMilliseconds(100ull)
    );

    if (NULL != loginClientFuncDescs[0])
    {
        // Add function 'loginClientSendRequest' of component instance 'loginClient' of type 'loginClient' to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            loginClientFuncDescs[0]->componentId,
            loginClientFuncDescs[0]->functionId,
            loginClientFuncDescs[0]->taskArgs,
            xme_hal_time_timeIntervalFromSeconds(0ull),
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != marshalerWaypointDescriptor)
    {
        // Add marshaler waypoint configuration for component port 'loginClient.outRequest'to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            marshalerWaypointDescriptor->componentId,
            marshalerWaypointDescriptor->functionId,
            (void *)(uintptr_t)marshalerWaypointInstanceIds[0],
            (xme_hal_time_timeInterval_t)1ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != udpSendWaypointDescriptor)
    {
        // Add udpsend waypoint configuration for component port 'loginClient.outRequest'to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            udpSendWaypointDescriptor->componentId,
            udpSendWaypointDescriptor->functionId,
            (void *)(uintptr_t)udpSendWaypointInstanceIds[0],
            (xme_hal_time_timeInterval_t)2ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != pnpClientFuncDescs[2])
    {
        // Add function 'pnpClientSendLogoutRequest' of component instance 'pnpClient' of type 'pnpClient' to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            pnpClientFuncDescs[2]->componentId,
            pnpClientFuncDescs[2]->functionId,
            pnpClientFuncDescs[2]->taskArgs,
            (xme_hal_time_timeInterval_t)3ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != pnpClientFuncDescs[3])
    {
        // Add function 'pnpClientSendRemoveComponentRequest' of component instance 'pnpClient' of type 'pnpClient' to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            pnpClientFuncDescs[3]->componentId,
            pnpClientFuncDescs[3]->functionId,
            pnpClientFuncDescs[3]->taskArgs,
            (xme_hal_time_timeInterval_t)4ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != udpReceiveWaypointDescriptor)
    {
        // Add udpreceive waypoint configuration for component port 'loginClient.inResponse'to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            udpReceiveWaypointDescriptor->componentId,
            udpReceiveWaypointDescriptor->functionId,
            (void *)(uintptr_t)udpReceiveWaypointInstanceIds[0],
            (xme_hal_time_timeInterval_t)5ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != demarshalerWaypointDescriptor)
    {
        // Add demarshaler waypoint configuration for component port 'loginClient.inResponse'to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            demarshalerWaypointDescriptor->componentId,
            demarshalerWaypointDescriptor->functionId,
            (void *)(uintptr_t)demarshalerWaypointInstanceIds[0],
            (xme_hal_time_timeInterval_t)6ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != loginClientFuncDescs[1])
    {
        // Add function 'loginClientProcessResponse' of component instance 'loginClient' of type 'loginClient' to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            loginClientFuncDescs[1]->componentId,
            loginClientFuncDescs[1]->functionId,
            loginClientFuncDescs[1]->taskArgs,
            (xme_hal_time_timeInterval_t)7ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != pnpClientFuncDescs[0])
    {
        // Add function 'pnpClientSendManifest' of component instance 'pnpClient' of type 'pnpClient' to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            pnpClientFuncDescs[0]->componentId,
            pnpClientFuncDescs[0]->functionId,
            pnpClientFuncDescs[0]->taskArgs,
            (xme_hal_time_timeInterval_t)8ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != udpReceiveWaypointDescriptor)
    {
        // Add udpreceive waypoint configuration for component port 'pnpClient.inGraph'to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            udpReceiveWaypointDescriptor->componentId,
            udpReceiveWaypointDescriptor->functionId,
            (void *)(uintptr_t)udpReceiveWaypointInstanceIds[1],
            (xme_hal_time_timeInterval_t)9ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != demarshalerWaypointDescriptor)
    {
        // Add demarshaler waypoint configuration for component port 'pnpClient.inGraph'to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            demarshalerWaypointDescriptor->componentId,
            demarshalerWaypointDescriptor->functionId,
            (void *)(uintptr_t)demarshalerWaypointInstanceIds[1],
            (xme_hal_time_timeInterval_t)10ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != pnpClientFuncDescs[1])
    {
        // Add function 'pnpClientProcessGraph' of component instance 'pnpClient' of type 'pnpClient' to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            pnpClientFuncDescs[1]->componentId,
            pnpClientFuncDescs[1]->functionId,
            pnpClientFuncDescs[1]->taskArgs,
            (xme_hal_time_timeInterval_t)11ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }
    if (NULL != exampleGUIFuncDescs[0])
    {
        // Add function 'doSomething' of component instance 'exampleGUI' of type 'exampleGUI' to schedule
        status = xme_core_exec_scheduler_addElementToScheduleTable
        (
            nodeSchedules[0],
            exampleGUIFuncDescs[0]->componentId,
            exampleGUIFuncDescs[0]->functionId,
            exampleGUIFuncDescs[0]->taskArgs,
            (xme_hal_time_timeInterval_t)12ull,
            (xme_hal_time_timeInterval_t)1ull,
            1,
            0,
            true
        );
        XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);
    }

    status = xme_core_exec_scheduler_registerSchedule(nodeSchedules[0], &scheduleId);
    XME_ASSERT_NORVAL(XME_STATUS_SUCCESS == status);

    // Activate schedule
    xme_core_exec_scheduler_activateSchedule(scheduleId);
}

xme_core_dataManager_dataPacketId_t
getDataPacketID
(
    xme_core_component_t componentID,
    uint16_t portIndex
)
{
    xme_status_t status;
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle;
    xme_core_nodeMgr_compRep_portHandle_t portHandle;

    status = xme_core_nodeMgr_compRep_getComponentInstance(XME_CORE_NODE_LOCAL_NODE_ID, componentID, &componentHandle);
    XME_ASSERT_RVAL(XME_STATUS_SUCCESS == status, XME_CORE_DATAMANAGER_DATAPACKETID_INVALID);

    portHandle = xme_core_nodeMgr_compRep_getPort(componentHandle, portIndex);

    return xme_core_nodeMgr_compRep_getDataPacketID(portHandle);
}

xme_core_exec_functionDescriptor_t*
getFunctionDescriptor
(
    xme_core_component_t componentID,
    uint16_t functionIndex
)
{
    xme_status_t status;
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle;
    xme_core_nodeMgr_compRep_functionHandle_t functionHandle;

    status = xme_core_nodeMgr_compRep_getComponentInstance(XME_CORE_NODE_LOCAL_NODE_ID, componentID, &componentHandle);
    XME_ASSERT_RVAL(XME_STATUS_SUCCESS == status, NULL);

    functionHandle = xme_core_nodeMgr_compRep_getFunction(componentHandle, functionIndex);

    return (xme_core_exec_functionDescriptor_t*)xme_core_nodeMgr_compRep_getFunctionDescriptor(functionHandle);
}

xme_status_t
createComponentInstances(void)
{
    xme_status_t status;

    // Create statically configured component instance 'loginClient' of type 'loginClient'
    {
        xme_core_nodeMgr_compRep_componentBuilder_t* builder = NULL;
        xme_core_nodeMgr_compRep_componentHandle_t componentHandle;

        builder = xme_core_nodeMgr_compRep_createBuilder(XME_CORE_NODE_LOCAL_NODE_ID, (xme_core_componentType_t)11);
        XME_CHECK_MSG(NULL != builder, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'loginClient' of type 'loginClient' failed. Builder could not be created.\n", __FILE__, __LINE__);
        xme_core_nodeMgr_compRep_builderSetComponentID(builder, (xme_core_component_t)2);
        status = xme_core_nodeMgr_compRep_build(builder, &componentHandle);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'loginClient' of type 'loginClient' failed. Building of component failed.\n", __FILE__, __LINE__);

        status = xme_core_nodeMgr_compRep_setStateToAnnounced(componentHandle);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'loginClient' of type 'loginClient' failed. Setting state to ANNOUNCED failed.\n", __FILE__, __LINE__);

        status = xme_core_nodeMgr_compRep_createAndRegisterComponent(componentHandle);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'loginClient' of type 'loginClient' failed. Registration and port allocation failed.\n", __FILE__, __LINE__);

        ports[1] = getDataPacketID((xme_core_component_t)2, 0);
        ports[2] = getDataPacketID((xme_core_component_t)2, 1);
        ports[3] = getDataPacketID((xme_core_component_t)2, 2);
        
        loginClientFuncDescs[0] = getFunctionDescriptor((xme_core_component_t)2, 0);
        loginClientFuncDescs[1] = getFunctionDescriptor((xme_core_component_t)2, 1);
    }
    
    // Create statically configured component instance 'pnpClient' of type 'pnpClient'
    {
        xme_core_nodeMgr_compRep_componentBuilder_t* builder = NULL;
        xme_core_nodeMgr_compRep_componentHandle_t componentHandle;

        builder = xme_core_nodeMgr_compRep_createBuilder(XME_CORE_NODE_LOCAL_NODE_ID, (xme_core_componentType_t)2);
        XME_CHECK_MSG(NULL != builder, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'pnpClient' of type 'pnpClient' failed. Builder could not be created.\n", __FILE__, __LINE__);
        xme_core_nodeMgr_compRep_builderSetComponentID(builder, (xme_core_component_t)4);
        status = xme_core_nodeMgr_compRep_build(builder, &componentHandle);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'pnpClient' of type 'pnpClient' failed. Building of component failed.\n", __FILE__, __LINE__);

        status = xme_core_nodeMgr_compRep_setStateToAnnounced(componentHandle);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'pnpClient' of type 'pnpClient' failed. Setting state to ANNOUNCED failed.\n", __FILE__, __LINE__);

        status = xme_core_nodeMgr_compRep_createAndRegisterComponent(componentHandle);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'pnpClient' of type 'pnpClient' failed. Registration and port allocation failed.\n", __FILE__, __LINE__);

        ports[4] = getDataPacketID((xme_core_component_t)4, 0);
        ports[5] = getDataPacketID((xme_core_component_t)4, 1);
        ports[6] = getDataPacketID((xme_core_component_t)4, 2);
        ports[7] = getDataPacketID((xme_core_component_t)4, 3);
        ports[8] = getDataPacketID((xme_core_component_t)4, 4);
        ports[9] = getDataPacketID((xme_core_component_t)4, 5);
        
        pnpClientFuncDescs[0] = getFunctionDescriptor((xme_core_component_t)4, 0);
        pnpClientFuncDescs[1] = getFunctionDescriptor((xme_core_component_t)4, 1);
        pnpClientFuncDescs[2] = getFunctionDescriptor((xme_core_component_t)4, 2);
        pnpClientFuncDescs[3] = getFunctionDescriptor((xme_core_component_t)4, 3);
    }
    
    // Create statically configured component instance 'exampleGUI' of type 'exampleGUI'
    {
        xme_core_nodeMgr_compRep_componentBuilder_t* builder = NULL;
        xme_core_nodeMgr_compRep_componentHandle_t componentHandle;

        builder = xme_core_nodeMgr_compRep_createBuilder(XME_CORE_NODE_LOCAL_NODE_ID, (xme_core_componentType_t)6097);
        XME_CHECK_MSG(NULL != builder, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'exampleGUI' of type 'exampleGUI' failed. Builder could not be created.\n", __FILE__, __LINE__);
        xme_core_nodeMgr_compRep_builderSetComponentID(builder, (xme_core_component_t)130);
        status = xme_core_nodeMgr_compRep_build(builder, &componentHandle);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'exampleGUI' of type 'exampleGUI' failed. Building of component failed.\n", __FILE__, __LINE__);

        status = xme_core_nodeMgr_compRep_setStateToAnnounced(componentHandle);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'exampleGUI' of type 'exampleGUI' failed. Setting state to ANNOUNCED failed.\n", __FILE__, __LINE__);

        status = xme_core_nodeMgr_compRep_createAndRegisterComponent(componentHandle);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Creation of component instance 'exampleGUI' of type 'exampleGUI' failed. Registration and port allocation failed.\n", __FILE__, __LINE__);

        ports[0] = getDataPacketID((xme_core_component_t)130, 0);
        
        exampleGUIFuncDescs[0] = getFunctionDescriptor((xme_core_component_t)130, 0);
    }

    return XME_STATUS_SUCCESS;
}
void
createWaypoints(void)
{
    createDemarshalerWaypointInstance
    (
        &demarshalerWaypointDescriptor,
        (xme_core_component_t)6
    );

    {
        // Add demarshaler configurations
        if (NULL != demarshalerWaypointDescriptor)
        {
            demarshalerWaypointAddConfig
            (
                demarshalerWaypointDescriptor,
                &ports[12], // demarshaler.configuration[0].in (loginClient.inResponse)
                1,
                &ports[10], // demarshaler.configuration[0].out (loginClient.inResponse)
                &demarshalerWaypointInstanceIds[0],
                XME_CORE_TOPIC_LOGIN_LOGINRESPONSE,
                sizeof(xme_core_topic_login_loginResponse_t),
                (xme_core_channelId_t)23
            );
            
            demarshalerWaypointAddConfig
            (
                demarshalerWaypointDescriptor,
                &ports[13], // demarshaler.configuration[1].in (pnpClient.inGraph)
                1,
                &ports[11], // demarshaler.configuration[1].out (pnpClient.inGraph)
                &demarshalerWaypointInstanceIds[1],
                XME_CORE_TOPIC_PNPMANAGER_RUNTIME_GRAPH_MODEL,
                sizeof(xme_core_topic_pnpManager_runtime_graph_model_t),
                (xme_core_channelId_t)10
            );
        }
    }
    
    createUdpReceiveWaypointInstance
    (
        &udpReceiveWaypointDescriptor,
        (xme_core_component_t)8
    );

    {
        // Add udp receive configurations
        if (NULL != udpReceiveWaypointDescriptor)
        {
            {
                uint8_t key[] = {0, 0, 0, 23};
        
                udpReceiveWaypointAddConfig
                (
                    udpReceiveWaypointDescriptor,
                    &ports[14], // udpReceive.configuration[0].out (loginClient.inResponse)
                    key,
                    65100,
                    XME_CORE_TOPIC_LOGIN_LOGINRESPONSE,
                    sizeof(xme_core_topic_login_loginResponse_t),
                    &udpReceiveWaypointInstanceIds[0],
                    &udpReceiveBuffers[0]
                );
            }
            {
                uint8_t key[] = {0, 0, 0, 10};
        
                udpReceiveWaypointAddConfig
                (
                    udpReceiveWaypointDescriptor,
                    &ports[15], // udpReceive.configuration[1].out (pnpClient.inGraph)
                    key,
                    65100,
                    XME_CORE_TOPIC_PNPMANAGER_RUNTIME_GRAPH_MODEL,
                    sizeof(xme_core_topic_pnpManager_runtime_graph_model_t),
                    &udpReceiveWaypointInstanceIds[1],
                    &udpReceiveBuffers[1]
                );
            }
        }
    }
    
    createMarshalerWaypointInstance
    (
        &marshalerWaypointDescriptor,
        (xme_core_component_t)5
    );

    {
        // Add marshaler configurations
        if (NULL != marshalerWaypointDescriptor)
        {
            marshalerWaypointAddConfig
            (
                marshalerWaypointDescriptor,
                &ports[17], // marshaler.configuration[0].in (loginClient.outRequest)
                1,
                &ports[16], // marshaler.configuration[0].out (loginClient.outRequest)
                &marshalerWaypointInstanceIds[0],
                XME_CORE_TOPIC_LOGIN_LOGINREQUEST,
                sizeof(xme_core_topic_login_loginRequest_t),
                (xme_core_channelId_t)22
            );
        }
    }
    
    createUdpSendWaypointInstance
    (
        &udpSendWaypointDescriptor,
        (xme_core_component_t)7
    );

    {
        // Add udp send configurations
        if (NULL != udpSendWaypointDescriptor)
        {
            {
                uint8_t key[] = {0, 0, 0, 22};
        
                udpSendWaypointAddConfig
                (
                    udpSendWaypointDescriptor,
                    &ports[18], // udpSend.configuration[0].in (loginClient.outRequest)
                    key,
                    g_addressBufferMulti,
                    33200,
                    XME_CORE_TOPIC_LOGIN_LOGINREQUEST,
                    sizeof(xme_core_topic_login_loginRequest_t),
                    &udpSendWaypointInstanceIds[0],
                    &udpSendBuffers[0],
                    true
                );
            }
        }
    }
}

xme_status_t
registerTopicsAndAttributes(void)
{
    // Register topic data size for topic 'pnpManager_runtime_graph_model'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_PNPMANAGER_RUNTIME_GRAPH_MODEL,
            sizeof(xme_core_topic_pnpManager_runtime_graph_model_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'pnpManager_runtime_graph_model'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_PNPMANAGER_RUNTIME_GRAPH_MODEL,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'pnpManager_runtime_graph_model' failed.\n");
        }
    }
    
    // Register topic data size for topic 'login_loginRequest'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_LOGIN_LOGINREQUEST,
            sizeof(xme_core_topic_login_loginRequest_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'login_loginRequest'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_LOGIN_LOGINREQUEST,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'login_loginRequest' failed.\n");
        }
    }
    
    // Register topic data size for topic 'login_loginResponse'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_LOGIN_LOGINRESPONSE,
            sizeof(xme_core_topic_login_loginResponse_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'login_loginResponse'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_LOGIN_LOGINRESPONSE,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'login_loginResponse' failed.\n");
        }
    }
    
    // Register topic data size for topic 'login_pnpLoginRequest'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_LOGIN_PNPLOGINREQUEST,
            sizeof(xme_core_topic_login_pnpLoginRequest_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'login_pnpLoginRequest'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_LOGIN_PNPLOGINREQUEST,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'login_pnpLoginRequest' failed.\n");
        }
    }
    
    // Register topic data size for topic 'login_pnpLoginResponse'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_LOGIN_PNPLOGINRESPONSE,
            sizeof(xme_core_topic_login_pnpLoginResponse_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'login_pnpLoginResponse'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_LOGIN_PNPLOGINRESPONSE,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'login_pnpLoginResponse' failed.\n");
        }
    }
    
    // Register topic data size for topic 'login_loginAcknowledgment'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_LOGIN_LOGINACKNOWLEDGMENT,
            sizeof(xme_core_topic_login_loginAcknowledgment_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'login_loginAcknowledgment'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_LOGIN_LOGINACKNOWLEDGMENT,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'login_loginAcknowledgment' failed.\n");
        }
    }
    
    // Register topic data size for topic 'pnp_componentInstanceManifest'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_PNP_COMPONENTINSTANCEMANIFEST,
            sizeof(xme_core_topic_pnp_componentInstanceManifest_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'pnp_componentInstanceManifest'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_PNP_COMPONENTINSTANCEMANIFEST,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'pnp_componentInstanceManifest' failed.\n");
        }
    }
    
    // Register topic data size for topic 'pnp_logoutAcknowledgment'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_PNP_LOGOUTACKNOWLEDGMENT,
            sizeof(xme_core_topic_pnp_logoutAcknowledgment_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'pnp_logoutAcknowledgment'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_PNP_LOGOUTACKNOWLEDGMENT,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'pnp_logoutAcknowledgment' failed.\n");
        }
    }
    
    // Register topic data size for topic 'pnp_logoutRequest'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_PNP_LOGOUTREQUEST,
            sizeof(xme_core_topic_pnp_logoutRequest_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'pnp_logoutRequest'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_PNP_LOGOUTREQUEST,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'pnp_logoutRequest' failed.\n");
        }
    }
    
    // Register topic data size for topic 'pnp_logoutNotification'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_PNP_LOGOUTNOTIFICATION,
            sizeof(xme_core_topic_pnp_logoutNotification_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'pnp_logoutNotification'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_PNP_LOGOUTNOTIFICATION,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'pnp_logoutNotification' failed.\n");
        }
    }
    
    // Register topic data size for topic 'pnp_removeComponentRequest'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            XME_CORE_TOPIC_PNP_REMOVECOMPONENTREQUEST,
            sizeof(xme_core_topic_pnp_removeComponentRequest_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'pnp_removeComponentRequest'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            XME_CORE_TOPIC_PNP_REMOVECOMPONENTREQUEST,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'pnp_removeComponentRequest' failed.\n");
        }
    }
    
    // Register topic data size for topic 'add_component'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            AUTOPNP_TOPIC_ADD_COMPONENT,
            sizeof(AutoPnP_topic_add_component_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'add_component'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            AUTOPNP_TOPIC_ADD_COMPONENT,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'add_component' failed.\n");
        }
    }
    
    // Register topic data size for topic 'remove_component'
    {
        xme_status_t status;

        status = xme_core_directory_topicRegistry_registerTopicSize
        (
            AUTOPNP_TOPIC_REMOVE_COMPONENT,
            sizeof(AutoPnP_topic_remove_component_t),
            false
        );

        XME_CHECK(XME_STATUS_SUCCESS == status, status);
    }

    // Register attribute descriptor list for topic 'remove_component'
    {
        xme_status_t status;
        xme_core_attribute_descriptor_list_t attributeDescriptorList;
        xme_core_attribute_descriptor_t attributeDescriptors[1];

        // Attribute 'channelID'
        attributeDescriptors[0].key = (xme_core_attribute_key_t) XME_CORE_ATTRIBUTE_KEY_CHANNELID;
        attributeDescriptors[0].size = sizeof(uint32_t);

        attributeDescriptorList.length = 1;
        attributeDescriptorList.element = attributeDescriptors;

        status = xme_core_directory_attribute_registerAttributeDescriptorList
        (
            AUTOPNP_TOPIC_REMOVE_COMPONENT,
            &attributeDescriptorList,
            false
        );

        if (status != XME_STATUS_SUCCESS)
        {
            XME_LOG(XME_LOG_WARNING, "Registration of attribute descriptor list for topic 'remove_component' failed.\n");
        }
    }

    return XME_STATUS_SUCCESS;
}

void
createComponentTypeManifests(void)
{
    xme_status_t status;

    // Create and add manifest for component type 'exampleGUI' to manifest repository
    {
        xme_core_componentManifest_t componentManifest;

        status = autoPnP_adv_exampleGUI_manifest_createComponentTypeManifest(&componentManifest);

        if (XME_STATUS_SUCCESS != status)
        {
            XME_LOG(XME_LOG_WARNING, "Creation of component type manifest for 'exampleGUI' failed.\n");
        }
        else
        {
            status = xme_core_manifestRepository_addComponentManifest(&componentManifest, false);

            if (XME_STATUS_SUCCESS != status)
            {
                XME_LOG(XME_LOG_WARNING, "Addtion of component type manifest to manifest repository failed for 'exampleGUI'.\n");
            }
        }
    }
    
    // Create and add manifest for component type 'loginClient' to manifest repository
    {
        xme_core_componentManifest_t componentManifest;

        status = xme_core_login_loginClient_manifest_createComponentTypeManifest(&componentManifest);
        
        if (XME_STATUS_SUCCESS != status)
        {
            XME_LOG(XME_LOG_WARNING, "Creation of component type manifest for 'loginClient' failed.\n");
        }
        else
        {
            status = xme_core_manifestRepository_addComponentManifest(&componentManifest, false);

            if (XME_STATUS_SUCCESS != status)
            {
                XME_LOG(XME_LOG_WARNING, "Addtion of component type manifest to manifest repository failed for 'loginClient'.\n");
            }
        }
    }
    
    // Create and add manifest for component type 'pnpClient' to manifest repository
    {
        xme_core_componentManifest_t componentManifest;

        status = xme_core_pnp_pnpClient_manifest_createComponentTypeManifest(&componentManifest);
        
        if (XME_STATUS_SUCCESS != status)
        {
            XME_LOG(XME_LOG_WARNING, "Creation of component type manifest for 'pnpClient' failed.\n");
        }
        else
        {
            status = xme_core_manifestRepository_addComponentManifest(&componentManifest, false);

            if (XME_STATUS_SUCCESS != status)
            {
                XME_LOG(XME_LOG_WARNING, "Addtion of component type manifest to manifest repository failed for 'pnpClient'.\n");
            }
        }
    }
}

void
registerComponentTypesInLoggingEngine(void)
{
    xme_status_t status;

    {
        // Register component type 'exampleGUI' in logging engine
        status = xme_core_log_registerComponent((xme_core_log_componentID_t) 6097, "exampleGUI", xme_core_log_getMinimumLogSeverityLevel());
        XME_LOG_IF
        (
            XME_STATUS_SUCCESS != status,
            XME_LOG_WARNING,
            "Registering component with type %" PRIu32 " in logging system failed!\n",
            6097
        );
    }
    
    {
        // Register component type 'loginClient' in logging engine
        status = xme_core_log_registerComponent((xme_core_log_componentID_t) 11, "loginClient", xme_core_log_getMinimumLogSeverityLevel());
        XME_LOG_IF
        (
            XME_STATUS_SUCCESS != status,
            XME_LOG_WARNING,
            "Registering component with type %" PRIu32 " in logging system failed!\n",
            11
        );
    }
    
    {
        // Register component type 'pnpClient' in logging engine
        status = xme_core_log_registerComponent((xme_core_log_componentID_t) 2, "pnpClient", xme_core_log_getMinimumLogSeverityLevel());
        XME_LOG_IF
        (
            XME_STATUS_SUCCESS != status,
            XME_LOG_WARNING,
            "Registering component with type %" PRIu32 " in logging system failed!\n",
            2
        );
    }
}


xme_status_t
createDemarshalerWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
)
{
    static xme_core_exec_functionDescriptor_t* desc = NULL;

    if (NULL == desc)
    {
        desc = (xme_core_exec_functionDescriptor_t*)
                xme_hal_mem_alloc(sizeof(xme_core_exec_functionDescriptor_t));
        XME_CHECK_MSG
        (
            NULL != desc,
            XME_STATUS_OUT_OF_RESOURCES,
            XME_LOG_ERROR,
            "%s:%d Allocation of function Descriptor failed.\n",
            __FILE__,
            __LINE__
        );
        xme_hal_mem_set(desc, 0, sizeof(xme_core_exec_functionDescriptor_t));
        desc->task = (xme_hal_sched_taskCallback_t)
                &(xme_wp_marshal_demarshalerFunctionWrapper_execute);
        desc->taskArgs = desc;
        desc->componentId = componentId;
        desc->functionId = (xme_core_component_functionId_t) 1;
        desc->wcet_ns = xme_hal_time_timeIntervalFromMilliseconds(5ull);

        xme_core_exec_dispatcher_createFunctionExecutionUnit(desc, true);

        xme_wp_marshal_demarshaler_init();
    }

    *descriptor = desc;

    return XME_STATUS_SUCCESS;
}

xme_status_t
demarshalerWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* inputDataPort,
    uint8_t inputPortQueueSize,
    xme_core_dataManager_dataPacketId_t* outputDataPort,
    xme_wp_waypoint_instanceId_t* instanceId,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_core_channelId_t channelID
)
{
    xme_status_t status;
    xme_core_attribute_descriptor_list_t attributeDescriptorList;

    xme_core_directory_attribute_getAttributeDescriptorList
    (
        topic,
        &attributeDescriptorList
    );

    // Create subscription port
    {
        uint8_t i = 0;
    
        status = xme_core_dataHandler_createDataPacket
        (
            sizeOfTopic,
            inputDataPort
        );
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        status = xme_core_dataHandler_setDataPacketQueueSize(*inputDataPort, inputPortQueueSize);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Setting queue size of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            status = xme_core_dataHandler_createAttribute
            (
                attributeDescriptorList.element[i].size,
                attributeDescriptorList.element[i].key,
                *inputDataPort
            );
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of attribute in data packet failed with status %d.\n", __FILE__, __LINE__, status);
        }
    }

    // Create publication port
    {
        uint8_t i = 0;
    
        status = xme_core_dataHandler_createDataPacket
        (
            sizeOfTopic,
            outputDataPort
        );
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            status = xme_core_dataHandler_createAttribute
            (
                attributeDescriptorList.element[i].size,
                attributeDescriptorList.element[i].key,
                *outputDataPort
            );
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of attribute in data packet failed with status %d.\n", __FILE__, __LINE__, status);
        }
    }

    status = xme_core_dataHandler_configure();
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Data handler configure call fails with status %d.\n", __FILE__, __LINE__, status);

    // Add waypoint configuration
    {
        xme_wp_marshal_demarshaler_addConfig
        (
            instanceId,
            topic,
            channelID,
            *inputDataPort,
            *outputDataPort
        );

        status = xme_core_pnp_pnpClient_announceStaticDemarshaler
        (
            inputDataPort,
            outputDataPort,
            topic,
            sizeOfTopic,
            *instanceId,
            descriptor,
            channelID
        );
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    status = xme_core_broker_addDataPacketToFunction
    (
        *inputDataPort,
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(*instanceId),
        true
    );
    XME_CHECK_MSG
    (
        XME_STATUS_SUCCESS == status,
        status,
        XME_LOG_WARNING,
        "%s:%d Addition of data packet to broker failed.\n",
        __FILE__,
        __LINE__
    );

    return XME_STATUS_SUCCESS;
}

xme_status_t
demarshalerWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* inputDataPort,
    xme_core_dataManager_dataPacketId_t* outputDataPort,
    xme_wp_waypoint_instanceId_t instanceId
)
{
    xme_status_t status;

    XME_UNUSED_PARAMETER(inputDataPort);
    XME_UNUSED_PARAMETER(outputDataPort);

    // De-Register with broker
    status = xme_core_broker_removeFunctionVariant
    (
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(instanceId)
    );
    if (XME_STATUS_SUCCESS != status)
    {
        XME_LOG
        (
            XME_LOG_WARNING,
            "%s:%d Removing the function variant from broker failed.\n",
            __FILE__,
            __LINE__
        );
    }

    // Remove waypoint configuration
    {
        status = xme_wp_marshal_demarshaler_removeConfig(instanceId);
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    // Destroy subscription port
    // TODO: Currently ports cannot be destroyed

    // Destroy publication port
    // TODO: Currently ports cannot be destroyed

    return XME_STATUS_SUCCESS;
}

void
destroyDemarshalerWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
)
{
    xme_core_broker_removeFunction
    (
        descriptor->componentId,
        descriptor->functionId
    );
    xme_hal_mem_free(descriptor);
}
xme_status_t
createUdpReceiveWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
)
{
    static xme_core_exec_functionDescriptor_t* desc = NULL;

    if (NULL == desc)
    {
        desc = (xme_core_exec_functionDescriptor_t*)
                xme_hal_mem_alloc(sizeof(xme_core_exec_functionDescriptor_t));
        XME_CHECK_MSG
        (
            NULL != desc,
            XME_STATUS_OUT_OF_RESOURCES,
            XME_LOG_ERROR,
            "%s:%d Allocation of function Descriptor failed.\n",
            __FILE__,
            __LINE__
        );
        xme_hal_mem_set(desc, 0, sizeof(xme_core_exec_functionDescriptor_t));
        desc->task = (xme_hal_sched_taskCallback_t)
                &(xme_wp_udp_udpReceive_udpReceiveWayPointFunctionWrapper_execute);
        desc->taskArgs = desc;
        desc->componentId = componentId;
        desc->functionId = (xme_core_component_functionId_t) 1;
        desc->wcet_ns = xme_hal_time_timeIntervalFromMilliseconds(5ull);

        xme_core_exec_dispatcher_createFunctionExecutionUnit(desc, true);

        xme_wp_udp_udpReceive_init();
    }

    *descriptor = desc;

    return XME_STATUS_SUCCESS;
}

xme_status_t
udpReceiveWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* dataPort,
    uint8_t* key,
    uint32_t ipPort,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_wp_waypoint_instanceId_t* instanceId,
    void** recvBuffer
)
{
    xme_status_t status;
    xme_core_attribute_descriptor_list_t attributeDescriptorList;

    xme_core_directory_attribute_getAttributeDescriptorList
    (
        topic,
        &attributeDescriptorList
    );

    // Create publication port
    {
        uint8_t i = 0;
    
        status = xme_core_dataHandler_createDataPacket
        (
            sizeOfTopic,
            dataPort
        );
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            status = xme_core_dataHandler_createAttribute
            (
                attributeDescriptorList.element[i].size,
                attributeDescriptorList.element[i].key,
                *dataPort
            );
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of attribute in data packet failed with status %d.\n", __FILE__, __LINE__, status);
        }
    }

    status = xme_core_dataHandler_configure();
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Data handler configure call fails with status %d.\n", __FILE__, __LINE__, status);

    // Add waypoint configuration
    {
        uint16_t bufferSize;
        uint8_t i;

        bufferSize = sizeOfTopic + xme_wp_udp_udpReceive_getPackageOverHead();

        // Add enough space for each attribute
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            bufferSize += attributeDescriptorList.element[i].size;
        }

        *recvBuffer = xme_hal_mem_alloc(bufferSize);
        XME_CHECK_MSG
        (
            NULL != *recvBuffer,
            XME_STATUS_INTERNAL_ERROR,
            XME_LOG_ERROR,
            "%s:%d Allocation of buffer failed.\n",
            __FILE__,
            __LINE__
        );

        status = xme_wp_udp_udpReceive_addConfig
        (
            instanceId,
            *dataPort,
            topic,
            sizeOfTopic,
            *recvBuffer,
            bufferSize,
            key,
            ipPort
        );
        XME_CHECK_MSG
        (
            XME_STATUS_SUCCESS == status,
            XME_STATUS_INTERNAL_ERROR,
            XME_LOG_ERROR,
            "%s:%d udpReceive addConfig failed.\n",
            __FILE__,
            __LINE__
        );

        status = xme_core_pnp_pnpClient_announceStaticUDPReceive
        (
            dataPort,
            key,
            ipPort,
            topic,
            sizeOfTopic,
            *instanceId,
            descriptor,
            *recvBuffer
        );
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    // Register with broker
    status = xme_core_broker_registerFunction
    (
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(*instanceId)
    );
    XME_CHECK_MSG
    (
        XME_STATUS_INVALID_PARAMETER != status && XME_STATUS_UNEXPECTED != status,
        status,
        XME_LOG_WARNING,
        "%s:%d Registeration with broker failed.\n",
        __FILE__,
        __LINE__
    );

    return XME_STATUS_SUCCESS;
}

xme_status_t
udpReceiveWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* dataPort,
    xme_wp_waypoint_instanceId_t instanceId,
    void* recvBuffer
)
{
    xme_status_t status;

    XME_UNUSED_PARAMETER(dataPort);

    // De-Register with broker
    status = xme_core_broker_removeFunctionVariant
    (
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(instanceId)
    );
    if (XME_STATUS_SUCCESS != status)
    {
        XME_LOG
        (
            XME_LOG_WARNING,
            "%s:%d Removing the function variant from broker failed.\n",
            __FILE__,
            __LINE__
        );
    }

    // Remove waypoint configuration
    {
        xme_hal_mem_free(recvBuffer);
        recvBuffer = NULL;
        status = xme_wp_udp_udpReceive_removeConfig(instanceId);
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    // Destroy publication
    // TODO: Currently ports cannot be destroyed

    return XME_STATUS_SUCCESS;
}

void
destroyUdpReceiveWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
)
{
    uint8_t i;

    // Free allocated buffers
    for (i = 0; i < sizeof(udpReceiveBuffers)/sizeof(udpReceiveBuffers[0]); i++)
    {
        xme_hal_mem_free(udpReceiveBuffers[i]);
    }

    xme_core_broker_removeFunction
    (
        descriptor->componentId,
        descriptor->functionId
    );
    xme_hal_mem_free(descriptor);
}
xme_status_t
createMarshalerWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
)
{
    static xme_core_exec_functionDescriptor_t* desc = NULL;

    if (NULL == desc)
    {
        desc = (xme_core_exec_functionDescriptor_t*)
                xme_hal_mem_alloc(sizeof(xme_core_exec_functionDescriptor_t));
        XME_CHECK_MSG
        (
            NULL != desc,
            XME_STATUS_OUT_OF_RESOURCES,
            XME_LOG_ERROR,
            "%s:%d Allocation of function Descriptor failed.\n",
            __FILE__,
            __LINE__
        );
        xme_hal_mem_set(desc, 0, sizeof(xme_core_exec_functionDescriptor_t));
        desc->task = (xme_hal_sched_taskCallback_t)
                &(xme_wp_marshal_marshalerFunctionWrapper_execute);
        desc->taskArgs = desc;
        desc->componentId = componentId;
        desc->functionId = (xme_core_component_functionId_t) 1;
        desc->wcet_ns = xme_hal_time_timeIntervalFromMilliseconds(5ull);

        xme_core_exec_dispatcher_createFunctionExecutionUnit(desc, true);

        xme_wp_marshal_marshaler_init();
    }

    *descriptor = desc;

    return XME_STATUS_SUCCESS;
}

xme_status_t
marshalerWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* inputDataPort,
    uint8_t inputPortQueueSize,
    xme_core_dataManager_dataPacketId_t* outputDataPort,
    xme_wp_waypoint_instanceId_t* instanceId,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_core_channelId_t channelID
)
{
    xme_status_t status;
    xme_core_attribute_descriptor_list_t attributeDescriptorList;

    xme_core_directory_attribute_getAttributeDescriptorList
    (
        topic,
        &attributeDescriptorList
    );

    // Create subscription port
    {
        uint8_t i = 0;
    
        status = xme_core_dataHandler_createDataPacket
        (
            sizeOfTopic,
            inputDataPort
        );
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        status = xme_core_dataHandler_setDataPacketQueueSize(*inputDataPort, inputPortQueueSize);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Setting queue size of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            status = xme_core_dataHandler_createAttribute
            (
                attributeDescriptorList.element[i].size,
                attributeDescriptorList.element[i].key,
                *inputDataPort
            );
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of attribute in data packet failed with status %d.\n", __FILE__, __LINE__, status);
        }
    }

    // Create publication port
    {
        uint8_t i = 0;
    
        status = xme_core_dataHandler_createDataPacket
        (
            sizeOfTopic,
            outputDataPort
        );
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            status = xme_core_dataHandler_createAttribute
            (
                attributeDescriptorList.element[i].size,
                attributeDescriptorList.element[i].key,
                *outputDataPort
            );
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of attribute in data packet failed with status %d.\n", __FILE__, __LINE__, status);
        }
    }

    status = xme_core_dataHandler_configure();
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Data handler configure call fails with status %d.\n", __FILE__, __LINE__, status);

    // Add waypoint configuration
    {
        xme_wp_marshal_marshaler_addConfig
        (
            instanceId,
            topic,
            channelID,
            *inputDataPort,
            *outputDataPort
        );

        status = xme_core_pnp_pnpClient_announceStaticMarshaler
        (
            inputDataPort,
            outputDataPort,
            topic,
            sizeOfTopic,
            *instanceId,
            descriptor,
            channelID
        );
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    status = xme_core_broker_addDataPacketToFunction
    (
        *inputDataPort,
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(*instanceId),
        true
    );
    XME_CHECK_MSG
    (
        XME_STATUS_SUCCESS == status,
        status,
        XME_LOG_WARNING,
        "%s:%d Addition of data packet to broker failed.\n",
        __FILE__,
        __LINE__
    );

    return XME_STATUS_SUCCESS;
}

xme_status_t
marshalerWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* inputDataPort,
    xme_core_dataManager_dataPacketId_t* outputDataPort,
    xme_wp_waypoint_instanceId_t instanceId
)
{
    xme_status_t status;

    XME_UNUSED_PARAMETER(inputDataPort);
    XME_UNUSED_PARAMETER(outputDataPort);

    // De-Register with broker
    status = xme_core_broker_removeFunctionVariant
    (
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(instanceId)
    );
    if (XME_STATUS_SUCCESS != status)
    {
        XME_LOG
        (
            XME_LOG_WARNING,
            "%s:%d Removing the function variant from broker failed.\n",
            __FILE__,
            __LINE__
        );
    }

    // Remove waypoint configuration
    {
        status = xme_wp_marshal_marshaler_removeConfig(instanceId);
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    // Destroy subscription port
    // TODO: Currently ports cannot be destroyed

    // Destroy publication port
    // TODO: Currently ports cannot be destroyed

    return XME_STATUS_SUCCESS;
}

void
destroyMarshalerWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
)
{
    xme_core_broker_removeFunction
    (
        descriptor->componentId,
        descriptor->functionId
    );
    xme_hal_mem_free(descriptor);
}

xme_status_t
createUdpSendWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
)
{
    static xme_core_exec_functionDescriptor_t* desc = NULL;

    if (NULL == desc)
    {
        desc = (xme_core_exec_functionDescriptor_t*)
               xme_hal_mem_alloc(sizeof(xme_core_exec_functionDescriptor_t));
        XME_CHECK_MSG
        (
            NULL != desc,
            XME_STATUS_OUT_OF_RESOURCES,
            XME_LOG_ERROR,
            "%s:%d Allocation of function Descriptor failed.\n",
            __FILE__,
            __LINE__
        );
        xme_hal_mem_set(desc, 0, sizeof(xme_core_exec_functionDescriptor_t));
        desc->task = (xme_hal_sched_taskCallback_t)
                &(xme_wp_udp_udpSend_udpSendWayPointFunctionWrapper_execute);
        desc->taskArgs = desc;
        desc->componentId = componentId;
        desc->functionId = (xme_core_component_functionId_t) 1;
        desc->wcet_ns = xme_hal_time_timeIntervalFromMilliseconds(5ull);

        xme_wp_udp_udpSend_init();

        xme_core_exec_dispatcher_createFunctionExecutionUnit(desc, true);
    }

    *descriptor = desc;

    return XME_STATUS_SUCCESS;
}

xme_status_t
udpSendWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* dataPort,
    uint8_t* key,
    const char* destIP,
    uint32_t ipPort,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_wp_waypoint_instanceId_t* instanceId,
    void** sendBuffer,
    bool isBroadcast
)
{
    xme_status_t status;
    xme_core_attribute_descriptor_list_t attributeDescriptorList;

    xme_core_directory_attribute_getAttributeDescriptorList
    (
        topic,
        &attributeDescriptorList
    );

    // Create subscription port
    {
        uint8_t i = 0;
    
        status = xme_core_dataHandler_createDataPacket
        (
            sizeOfTopic,
            dataPort
        );
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            status = xme_core_dataHandler_createAttribute
            (
                attributeDescriptorList.element[i].size,
                attributeDescriptorList.element[i].key,
                *dataPort
            );
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of attribute in data packet failed with status %d.\n", __FILE__, __LINE__, status);
        }
    }

    status = xme_core_dataHandler_configure();
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Data handler configure call fails with status %d.\n", __FILE__, __LINE__, status);

    // Add waypoint configuration
    {
        uint16_t bufferSize;
        uint8_t i;

        bufferSize = sizeOfTopic + xme_wp_udp_udpSend_getPackageOverHead();

        // Add enough space for each attribute
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            bufferSize += attributeDescriptorList.element[i].size;
        }

        *sendBuffer = xme_hal_mem_alloc(bufferSize);
        XME_CHECK_MSG
        (
            NULL != *sendBuffer,
            XME_STATUS_INTERNAL_ERROR,
            XME_LOG_ERROR,
            "%s:%d Allocation of buffer failed.\n",
            __FILE__,
            __LINE__
        );

        status = xme_wp_udp_udpSend_addConfig
        (
            instanceId,
            *dataPort,
            topic,
            sizeOfTopic,
            *sendBuffer,
            bufferSize,
            key,
            destIP,
            ipPort,
            isBroadcast
        );
        XME_CHECK_MSG
        (
            XME_STATUS_SUCCESS == status,
            XME_STATUS_INTERNAL_ERROR,
            XME_LOG_ERROR,
            "%s:%d udpSend addConfig failed.\n",
            __FILE__,
            __LINE__
        );

        status = xme_core_pnp_pnpClient_announceStaticUDPSend
        (
            dataPort,
            key,
            destIP,
            ipPort,
            topic,
            sizeOfTopic,
            *instanceId,
            descriptor,
            *sendBuffer
        );
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    status = xme_core_broker_addDataPacketToFunction
    (
        *dataPort,
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(*instanceId),
        true
    );
    XME_CHECK_MSG
    (
        XME_STATUS_SUCCESS == status,
        status,
        XME_LOG_WARNING,
        "%s:%d Addition of data packet to broker failed.\n",
        __FILE__,
        __LINE__
    );

    return XME_STATUS_SUCCESS;
}

xme_status_t
udpSendWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* dataPort,
    xme_wp_waypoint_instanceId_t instanceId,
    void* sendBuffer
)
{
    xme_status_t status;

    XME_UNUSED_PARAMETER(dataPort);

    // De-Register with broker
    status = xme_core_broker_removeFunctionVariant
    (
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(instanceId)
    );
    if (XME_STATUS_SUCCESS != status)
    {
        XME_LOG
        (
            XME_LOG_WARNING,
            "%s:%d Removing the function variant from broker failed.\n",
            __FILE__,
            __LINE__
        );
    }

    // Remove waypoint configuration
    {
        xme_hal_mem_free(sendBuffer);
        sendBuffer = NULL;
        status = xme_wp_udp_udpSend_removeConfig(instanceId);
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    // Destroy subscription
    // TODO: Currently ports cannot be destroyed

    return XME_STATUS_SUCCESS;
}

void
destroyUdpSendWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
)
{
    uint8_t i;


    // Free allocated buffers
    for (i = 0; i < sizeof(udpSendBuffers)/sizeof(udpSendBuffers[0]); i++)
    {
        xme_hal_mem_free(udpSendBuffers[i]);
    }
    xme_core_broker_removeFunction
    (
        descriptor->componentId,
        descriptor->functionId
    );
    xme_hal_mem_free(descriptor);
}
xme_status_t
createChannelInjectorWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
)
{
    static xme_core_exec_functionDescriptor_t* desc = NULL;

    if (NULL == desc)
    {
        desc = (xme_core_exec_functionDescriptor_t*)
                xme_hal_mem_alloc(sizeof(xme_core_exec_functionDescriptor_t));
        XME_CHECK_MSG
        (
            NULL != desc,
            XME_STATUS_OUT_OF_RESOURCES,
            XME_LOG_ERROR,
            "%s:%d Allocation of function Descriptor failed.\n",
            __FILE__,
            __LINE__
        );
        xme_hal_mem_set(desc, 0, sizeof(xme_core_exec_functionDescriptor_t));
        desc->task = (xme_hal_sched_taskCallback_t)
                &(xme_wp_channel_channelInjector_channelInjectorWayPointFunctionWrapper_execute);
        desc->taskArgs = desc;
        desc->componentId = componentId;
        desc->functionId = (xme_core_component_functionId_t) 1;
        desc->wcet_ns = xme_hal_time_timeIntervalFromMilliseconds(5ull);

        xme_core_exec_dispatcher_createFunctionExecutionUnit(desc, true);

        xme_wp_channel_channelInjector_init();
    }

    *descriptor = desc;

    return XME_STATUS_SUCCESS;
}

xme_status_t
channelInjectorWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_core_dataManager_dataPacketId_t* inputPort,
    uint8_t inputPortQueueSize,
    xme_core_dataManager_dataPacketId_t* outputPort,
    xme_core_channelId_t injectedChannelID,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_wp_waypoint_instanceId_t* instanceId,
    void** recvBuffer
)
{
    xme_status_t status;
    xme_core_attribute_descriptor_list_t attributeDescriptorList;

    xme_core_directory_attribute_getAttributeDescriptorList
    (
        topic,
        &attributeDescriptorList
    );

    // Create subscription port
    {
        uint8_t i = 0;
    
        status = xme_core_dataHandler_createDataPacket
        (
            sizeOfTopic,
            inputPort
        );
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        status = xme_core_dataHandler_setDataPacketQueueSize(*inputPort, inputPortQueueSize);
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Setting queue size of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            status = xme_core_dataHandler_createAttribute
            (
                attributeDescriptorList.element[i].size,
                attributeDescriptorList.element[i].key,
                *inputPort
            );
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of attribute in data packet failed with status %d.\n", __FILE__, __LINE__, status);
        }
    }

    // Create publication port
    {
        uint8_t i = 0;
    
        status = xme_core_dataHandler_createDataPacket
        (
            sizeOfTopic,
            outputPort
        );
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            status = xme_core_dataHandler_createAttribute
            (
                attributeDescriptorList.element[i].size,
                attributeDescriptorList.element[i].key,
                *outputPort
            );
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of attribute in data packet failed with status %d.\n", __FILE__, __LINE__, status);
        }
    }

    status = xme_core_dataHandler_configure();
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Data handler configure call fails with status %d.\n", __FILE__, __LINE__, status);

    // Add waypoint configuration
    {
        uint16_t bufferSize;
        uint8_t i;

        bufferSize = sizeOfTopic;

        // Add enough space for each attribute
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            bufferSize += attributeDescriptorList.element[i].size;
        }

        *recvBuffer = xme_hal_mem_alloc(bufferSize);
        XME_CHECK_MSG
        (
            NULL != *recvBuffer,
            XME_STATUS_INTERNAL_ERROR,
            XME_LOG_ERROR,
            "%s:%d Allocation of buffer failed.\n",
            __FILE__,
            __LINE__
        );

        status = xme_wp_channel_channelInjector_addConfig
        (
            instanceId,
            *inputPort,
            *outputPort,
            topic,
            sizeOfTopic,
            *recvBuffer,
            bufferSize,
            injectedChannelID
        );
        XME_CHECK_MSG
        (
            XME_STATUS_SUCCESS == status,
            XME_STATUS_INTERNAL_ERROR,
            XME_LOG_ERROR,
            "%s:%d channelInjector addConfig failed.\n",
            __FILE__,
            __LINE__
        );

        status = xme_core_pnp_pnpClient_announceStaticChannelInjector
        (
            inputPort,
            outputPort,
            injectedChannelID,
            topic,
            sizeOfTopic,
            *instanceId,
            descriptor,
            *recvBuffer
        );
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    status = xme_core_broker_addDataPacketToFunction
    (
        *inputPort,
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(*instanceId),
        true
    );
    XME_CHECK_MSG
    (
        XME_STATUS_SUCCESS == status,
        status,
        XME_LOG_WARNING,
        "%s:%d Addition of data packet to broker failed.\n",
        __FILE__,
        __LINE__
    );

    return XME_STATUS_SUCCESS;
}

xme_status_t
channelInjectorWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_wp_waypoint_instanceId_t instanceId,
    xme_core_dataManager_dataPacketId_t* inputPort,
    xme_core_dataManager_dataPacketId_t* outputPort,
    void* recvBuffer
)
{
    xme_status_t status;

    XME_UNUSED_PARAMETER(inputPort);
    XME_UNUSED_PARAMETER(outputPort);

    // De-Register with broker
    status = xme_core_broker_removeFunctionVariant
    (
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(instanceId)
    );
    if (XME_STATUS_SUCCESS != status)
    {
        XME_LOG
        (
            XME_LOG_WARNING,
            "%s:%d Removing the function variant from broker failed.\n",
            __FILE__,
            __LINE__
        );
    }

    // Remove waypoint configuration
    {
        xme_hal_mem_free(recvBuffer);
        recvBuffer = NULL;
        status = xme_wp_channel_channelInjector_removeConfig(instanceId);
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    // Destroy subscription port
    // TODO: Currently ports cannot be destroyed

    // Destroy publication port
    // TODO: Currently ports cannot be destroyed

    return XME_STATUS_SUCCESS;
}

void
destroyChannelInjectorWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
)
{
    xme_core_broker_removeFunction
    (
        descriptor->componentId,
        descriptor->functionId
    );
    xme_hal_mem_free(descriptor);
}
xme_status_t
createChannelSelectorWaypointInstance
(
    xme_core_exec_functionDescriptor_t** descriptor,
    xme_core_component_t componentId
)
{
    static xme_core_exec_functionDescriptor_t* desc = NULL;

    if (NULL == desc)
    {
        desc = (xme_core_exec_functionDescriptor_t*)
                xme_hal_mem_alloc(sizeof(xme_core_exec_functionDescriptor_t));
        XME_CHECK_MSG
        (
            NULL != desc,
            XME_STATUS_OUT_OF_RESOURCES,
            XME_LOG_ERROR,
            "%s:%d Allocation of function Descriptor failed.\n",
            __FILE__,
            __LINE__
        );
        xme_hal_mem_set(desc, 0, sizeof(xme_core_exec_functionDescriptor_t));
        desc->task = (xme_hal_sched_taskCallback_t)
                &(xme_wp_channel_channelSelector_channelSelectorWayPointFunctionWrapper_execute);
        desc->taskArgs = desc;
        desc->componentId = componentId;
        desc->functionId = (xme_core_component_functionId_t) 1;
        desc->wcet_ns = xme_hal_time_timeIntervalFromMilliseconds(5ull);

        xme_core_exec_dispatcher_createFunctionExecutionUnit(desc, true);

        xme_wp_channel_channelSelector_init();
    }

    *descriptor = desc;

    return XME_STATUS_SUCCESS;
}

xme_status_t
channelSelectorWaypointAddConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_wp_waypoint_instanceId_t* instanceId,
    xme_core_dataManager_dataPacketId_t* inputPort,
    uint8_t inputPortQueueSize,
    xme_core_dataManager_dataPacketId_t* outputPort,
    xme_core_topic_t topic,
    uint16_t sizeOfTopic,
    xme_core_channelId_t sourceChannelID,
    xme_core_channelId_t destinationChannelID,
    void** recvBuffer
)
{
    uint16_t bufferSize = 0;
    xme_status_t status;
    xme_core_attribute_descriptor_list_t attributeDescriptorList;
    bool hasConfig = false;

    // When the channel configurator already has a configuration for the given topic, then
    // we do not create a new input port, but pass XME_CORE_DATAMANAGER_DATAPACKETID_INVALID.
    // Therefore, here inputPort is set to a valid data packet ID or
    // XME_CORE_DATAMANAGER_DATAPACKETID_INVALID by hasConfig function based on the fact 
    // that if there exists a configuration or not.

    hasConfig = xme_wp_channel_channelSelector_hasConfig(topic, inputPort);

    xme_core_directory_attribute_getAttributeDescriptorList
    (
        topic,
        &attributeDescriptorList
    );

    // Create input port only, when we do not have a configuration for the given topic yet
    // (all channel mappings for the same topic share a configuration)
    if (!hasConfig)
    {
        // Create subscription port
        {
            uint8_t i = 0;
        
            status = xme_core_dataHandler_createDataPacket
            (
                sizeOfTopic,
                inputPort
            );
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of data packet failed with status %d.\n", __FILE__, __LINE__, status);
        
            status = xme_core_dataHandler_setDataPacketQueueSize(*inputPort, inputPortQueueSize);
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Setting queue size of data packet failed with status %d.\n", __FILE__, __LINE__, status);
        
            for (i = 0; i < attributeDescriptorList.length; i++)
            {
                status = xme_core_dataHandler_createAttribute
                (
                    attributeDescriptorList.element[i].size,
                    attributeDescriptorList.element[i].key,
                    *inputPort
                );
                XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of attribute in data packet failed with status %d.\n", __FILE__, __LINE__, status);
            }
        }

        // Allocate buffer
        {
            uint8_t i;

            bufferSize = sizeOfTopic;

            // Add enough space for each attribute
            for (i = 0; i < attributeDescriptorList.length; i++)
            {
                bufferSize += attributeDescriptorList.element[i].size;
            }

            *recvBuffer = xme_hal_mem_alloc(bufferSize);
            XME_CHECK_MSG
            (
                NULL != *recvBuffer,
                XME_STATUS_INTERNAL_ERROR,
                XME_LOG_ERROR,
                "%s:%d Allocation of buffer failed.\n",
                __FILE__,
                __LINE__
            );
        }
    }
    else
    {
        *recvBuffer = NULL;
    }

    // Create publication port
    {
        uint8_t i = 0;
    
        status = xme_core_dataHandler_createDataPacket
        (
            sizeOfTopic,
            outputPort
        );
        XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of data packet failed with status %d.\n", __FILE__, __LINE__, status);
    
        for (i = 0; i < attributeDescriptorList.length; i++)
        {
            status = xme_core_dataHandler_createAttribute
            (
                attributeDescriptorList.element[i].size,
                attributeDescriptorList.element[i].key,
                *outputPort
            );
            XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Creation of attribute in data packet failed with status %d.\n", __FILE__, __LINE__, status);
        }
    }

    status = xme_core_dataHandler_configure();
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_ERROR, "%s:%d Data handler configure call fails with status %d.\n", __FILE__, __LINE__, status);

    // Add waypoint configuration
    status = xme_wp_channel_channelSelector_addConfig
    (
        instanceId,
        *inputPort,
        *outputPort,
        topic,
        sizeOfTopic,
        *recvBuffer,
        bufferSize,
        sourceChannelID,
        destinationChannelID
    );
    XME_CHECK_MSG
    (
        XME_STATUS_SUCCESS == status,
        XME_STATUS_INTERNAL_ERROR,
        XME_LOG_ERROR,
        "%s:%d channelSelector addConfig failed.\n",
        __FILE__,
        __LINE__
    );
    
    if (!hasConfig)
    {
        // Broker registration
        status = xme_core_broker_addDataPacketToFunction
        (
            *inputPort,
            descriptor->componentId,
            descriptor->functionId,
            (xme_core_component_functionVariantId_t)(*instanceId),
            true
        );
        XME_CHECK_MSG
        (
            XME_STATUS_SUCCESS == status,
            status,
            XME_LOG_WARNING,
            "%s:%d Addition of data packet to broker failed.\n",
            __FILE__,
            __LINE__
        );
    }
    
    status = xme_core_pnp_pnpClient_announceStaticChannelSelector
    (
        inputPort,
        outputPort,
        sourceChannelID,
        destinationChannelID,
        topic,
        sizeOfTopic,
        *instanceId,
        descriptor,
        *recvBuffer
    );
    XME_ASSERT(XME_STATUS_SUCCESS == status);


    // TODO: Error recovery

    return XME_STATUS_SUCCESS;
}

xme_status_t
channelSelectorWaypointRemoveConfig
(
    xme_core_exec_functionDescriptor_t* descriptor,
    xme_wp_waypoint_instanceId_t instanceId,
    xme_core_dataManager_dataPacketId_t* inputPort,
    xme_core_dataManager_dataPacketId_t* outputPort,
    xme_core_topic_t topic,
    xme_core_channelId_t sourceChannelID,
    xme_core_channelId_t destinationChannelID,
    void* recvBuffer
)
{
    xme_status_t status;
    xme_core_dataManager_dataPacketId_t tempInputPort;

    XME_UNUSED_PARAMETER(inputPort);
    XME_UNUSED_PARAMETER(outputPort);

    // De-Register with broker
    status = xme_core_broker_removeFunctionVariant
    (
        descriptor->componentId,
        descriptor->functionId,
        (xme_core_component_functionVariantId_t)(instanceId)
    );
    if (XME_STATUS_SUCCESS != status)
    {
        XME_LOG
        (
            XME_LOG_WARNING,
            "%s:%d Removing the function variant from broker failed.\n",
            __FILE__,
            __LINE__
        );
    }

    // Remove waypoint configuration
    {
        status = xme_wp_channel_channelSelector_removeConfig
        (
            instanceId,
            sourceChannelID,
            destinationChannelID
        );
        XME_ASSERT(XME_STATUS_SUCCESS == status);
    }

    if (!xme_wp_channel_channelSelector_hasConfig(topic, &tempInputPort))
    {
        xme_hal_mem_free(recvBuffer);
        recvBuffer = NULL;

        // Destroy subscription port
        // TODO: Currently ports cannot be destroyed
    }

    // Destroy publication port
    // TODO: Currently ports cannot be destroyed

    return XME_STATUS_SUCCESS;
}

void
destroyChannelSelectorWaypointInstance
(
    xme_core_exec_functionDescriptor_t* descriptor
)
{
    xme_core_broker_removeFunction
    (
        descriptor->componentId,
        descriptor->functionId
    );

    xme_hal_mem_free(descriptor);

    // Destroy ports
    // TODO: Currently ports cannot be destroyed
}

// Disable warning about unexpected exceptions. See issue #3848.
#if _MSC_VER && defined(__cplusplus)
    #pragma warning( pop )
#endif

xme_status_t
addDataPacketTransferEntries(void)
{
    xme_status_t status;

    status = xme_core_broker_addDataPacketTransferEntry(ports[2], ports[17]); // loginClient.outRequest -> marshaler.configuration[0].in (loginClient.outRequest)
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Call to xme_core_broker_addDataPacketTransferEntry() failed for source data packet ID %d and destination data packet ID %d with status %d.\n", __FILE__, __LINE__, ports[2], ports[17], status);
    status = xme_core_broker_addDataPacketTransferEntry(ports[3], ports[4]); // loginClient.outLoginAcknowledgment -> pnpClient.inLoginAcknowledgment
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Call to xme_core_broker_addDataPacketTransferEntry() failed for source data packet ID %d and destination data packet ID %d with status %d.\n", __FILE__, __LINE__, ports[3], ports[4], status);
    status = xme_core_broker_addDataPacketTransferEntry(ports[10], ports[1]); // demarshaler.configuration[0].out (loginClient.inResponse) -> loginClient.inResponse
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Call to xme_core_broker_addDataPacketTransferEntry() failed for source data packet ID %d and destination data packet ID %d with status %d.\n", __FILE__, __LINE__, ports[10], ports[1], status);
    status = xme_core_broker_addDataPacketTransferEntry(ports[11], ports[5]); // demarshaler.configuration[1].out (pnpClient.inGraph) -> pnpClient.inGraph
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Call to xme_core_broker_addDataPacketTransferEntry() failed for source data packet ID %d and destination data packet ID %d with status %d.\n", __FILE__, __LINE__, ports[11], ports[5], status);
    status = xme_core_broker_addDataPacketTransferEntry(ports[14], ports[12]); // udpReceive.configuration[0].out (loginClient.inResponse) -> demarshaler.configuration[0].in (loginClient.inResponse)
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Call to xme_core_broker_addDataPacketTransferEntry() failed for source data packet ID %d and destination data packet ID %d with status %d.\n", __FILE__, __LINE__, ports[14], ports[12], status);
    status = xme_core_broker_addDataPacketTransferEntry(ports[15], ports[13]); // udpReceive.configuration[1].out (pnpClient.inGraph) -> demarshaler.configuration[1].in (pnpClient.inGraph)
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Call to xme_core_broker_addDataPacketTransferEntry() failed for source data packet ID %d and destination data packet ID %d with status %d.\n", __FILE__, __LINE__, ports[15], ports[13], status);
    status = xme_core_broker_addDataPacketTransferEntry(ports[16], ports[18]); // marshaler.configuration[0].out (loginClient.outRequest) -> udpSend.configuration[0].in (loginClient.outRequest)
    XME_CHECK_MSG(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR, XME_LOG_FATAL, "%s:%d Call to xme_core_broker_addDataPacketTransferEntry() failed for source data packet ID %d and destination data packet ID %d with status %d.\n", __FILE__, __LINE__, ports[16], ports[18], status);

    return XME_STATUS_SUCCESS;
}

//#include <QApplication>

int
main(int argc, char* argv[])
{
    //QApplication app(argc, argv);

    xme_status_t status;

    status = xmeInit(argc, argv);
    XME_CHECK_MSG
    (
        XME_STATUS_SUCCESS == status,
        status,
        XME_LOG_FATAL,
        "Error occurred during initialization of CHROMOSOME core components. Aborting execution.\n"
    );

    xme_hal_env_setConsoleTitle("demonstrator");

    createComponentTypeManifests();

    status = registerTopicsAndAttributes();
    XME_CHECK_MSG
    (
        XME_STATUS_SUCCESS == status,
        status,
        XME_LOG_FATAL,
        "Registration of topics and attributes failed. Aborting execution.\n"
    );

    // PROTECTED REGION ID(DEMONSTRATOR_MAIN_BEFORE_COMPONENT_CREATION) ENABLED START
    // PROTECTED REGION END

    status = createComponentInstances();
    XME_CHECK(XME_STATUS_SUCCESS == status, status);

    status = pnpInit();
    XME_CHECK_MSG
    (
        XME_STATUS_SUCCESS == status,
        status,
        XME_LOG_FATAL,
        "Error occurred during initialization of CHROMOSOME plug and play components. Aborting execution.\n"
    );

    createWaypoints();

    status = addDataPacketTransferEntries();
    XME_CHECK(XME_STATUS_SUCCESS == status, status);

    configureSchedule();

    // PROTECTED REGION ID(DEMONSTRATOR_MAIN_RUN_BEFORE) ENABLED START
    // PROTECTED REGION END

    // Run the schedule
    xme_core_exec_run(0, false);
    //app.exec();

    // PROTECTED REGION ID(DEMONSTRATOR_MAIN_RUN_AFTER) ENABLED START
    // PROTECTED REGION END

    xme_core_exec_fini();

    // Destroy waypoints
    if (NULL != demarshalerWaypointDescriptor)
    {
        destroyDemarshalerWaypointInstance(demarshalerWaypointDescriptor);
    }
    if (NULL != udpReceiveWaypointDescriptor)
    {
        destroyUdpReceiveWaypointInstance(udpReceiveWaypointDescriptor);
    }
    if (NULL != marshalerWaypointDescriptor)
    {
        destroyMarshalerWaypointInstance(marshalerWaypointDescriptor);
    }
    if (NULL != udpSendWaypointDescriptor)
    {
        destroyUdpSendWaypointInstance(udpSendWaypointDescriptor);
    }

    XME_LOG(XME_LOG_NOTE, "Node demonstrator (nodeID %d) has shut down.\n", xme_core_node_getCurrentNodeId());

    xmeFini();

    return 0;
}
